diff --git a/PROJECT1 : THREADS/1. Intoduction.md b/PROJECT1 : THREADS/1. Intoduction.md
new file mode 100644
index 0000000000000000000000000000000000000000..e5bea5b024f51cb66a53e827e6ccbf675f44d93f
--- /dev/null
+++ b/PROJECT1 : THREADS/1. Intoduction.md	
@@ -0,0 +1,161 @@
+### 프로젝트 1: 스레드 (Threads)
+
+이 과제에서는 최소한의 기능을 가진 스레드 시스템을 제공합니다. 여러분의 과제는 이 시스템의 기능을 확장하여 동기화 문제를 더 깊이 이해하는 것입니다. 이 과제는 주로 `threads` 디렉토리에서 진행되며, 일부 작업은 `devices` 디렉토리에서 수행됩니다. 컴파일은 threads 디렉토리에서 이루어져야 합니다. 프로젝트 설명을 읽기 전에 `Synchronization`(동기화) 자료를 최소한 훑어보는 것이 좋습니다.
+
+### 배경 지식
+
+## 스레드 이해하기
+
+첫 번째 단계는 초기 스레드 시스템 코드를 읽고 이해하는 것입니다. Pintos는 이미 스레드 생성과 종료, 스레드 간 전환을 위한 간단한 스케줄러, 그리고 동기화 프리미티브(세마포어, 락, 조건 변수, 최적화 방지 장치)를 구현하고 있습니다.
+
+이 코드의 일부는 약간 이해하기 어려울 수 있습니다. 아직 Introduction에 설명된 대로 기본 시스템을 컴파일하고 실행해보지 않았다면, 지금 실행해보십시오. 소스 코드의 일부를 읽고 어떤 일이 발생하는지 확인할 수 있습니다. 필요하다면 `printf()`를 거의 어디에나 추가하여 코드를 다시 컴파일하고 실행하면서 어떤 일이 발생하고 어떤 순서로 실행되는지 확인할 수 있습니다. 또한 커널을 디버거로 실행하고, 흥미로운 지점에 중단점을 설정하거나, 코드를 단계별로 실행하고 데이터를 확인할 수도 있습니다.
+
+스레드가 생성되면 스케줄링 할 새로운 실행 컨텍스트가 생성됩니다. 이 컨텍스트에서 실행할 함수는 thread_create()의 인자로 전달됩니다. 스레드가 처음 스케줄링되고 실행되면 이 함수의 시작부터 실행을 시작하며, 해당 컨텍스트 내에서 실행됩니다. 이 함수가 반환되면 스레드는 종료됩니다. 따라서 각 스레드는 Pintos 내부에서 실행되는 작은 프로그램처럼 동작하며, `thread_create()`에 전달된 함수는 이 프로그램의 `main()`처럼 작동합니다.
+
+항상 한번에 정확히 한 스레드만 실행되며, 나머지 스레드는 비활성 상태가 됩니다. 스케줄러는 다음에 실행할 스레드를 결정합니다. (주어진 시점에 실행 준비가 된 스레드가 없다면, `idle()`에서 구현된 특수한 idle thread가 실행됩니다.) 동기화 원시는 한 스레드가 다른 스레드의 작업을 기다려야 할 때 컨텍스트 전환을 강제할 수 있습니다.
+
+컨텍스트 전환의 동작은 `threads/thread.c`의 `thread_launch()`에 있습니다. (이 부분을 이해할 필요는 없습니다.) 이 함수는 현재 실행 중인 스레드의 상태를 저장하고, 전환할 스레드의 상태를 복원합니다.
+
+GDB 디버거를 사용하여 컨텍스트 전환의 동작을 천천히 추적해보십시오(GDB를 참고하세요). `schedule()`에 중단점을 설정한 후, 그 지점부터 단계별로 실행해보세요. 각 스레드의 주소와 상태를 추적하고, 각 스레드의 호출 스택에 어떤 프로시저가 있는지 확인하십시오. `do_iret()`에서 `iret` 명령어가 실행되면 다른 스레드로 전환되는 것을 확인할 수 있습니다.
+
+Warning: Pintos에서는 각 스레드에 4kB 미만의 작은, 고정된 실행 스택이 할당됩니다. 커널은 스택 오버플로를 감지하려고 하지만 완벽하게 감지할 수는 없습니다. 예를 들어, `int buf[1000];`와 같은 큰 데이터 구조를 비정적 지역 변수로 선언하면 스택 오버플로로 인해 예기치 않은 커널 패닉 등과 같은 문제가 발생할 수 있습니다. 스택 할당 대신 페이지 할당자와 블록 할당자를 사용할 수 있습니다. (자세한 내용은 Memory Allocation을 참조하십시오.)
+
+## 소스 파일
+
+아래는 threads 디렉토리와 include/threads 디렉토리에 있는 파일들에 대한 간략한 개요입니다. 이 코드의 대부분은 수정할 필요가 없지만, 이 개요를 통해 어떤 코드를 살펴봐야 할지 감을 잡을 수 있기를 바랍니다.
+
+# threads 코드
+
+•loader.S, loader.h
+커널 로더. 512바이트의 코드와 데이터로 구성되어 PC BIOS가 이를 메모리에 로드하고, 이후 디스크에서 커널을 찾아 메모리에 로드한 후 start.S의 bootstrap()으로 점프합니다. 이 코드를 수정하거나 살펴볼 필요는 없습니다. start.S는 메모리 보호 설정과 64비트 긴 모드 전환을 위한 기본 설정 코드입니다. loader와 달리 이 코드는 실제로 커널의 일부입니다.
+
+•kernel.lds.S
+커널을 링크하는 데 사용되는 링크 스크립트입니다. 커널의 로드 주소를 설정하고, start.S가 커널 이미지의 시작 부분 근처에 배치합니다. 이 코드를 수정하거나 살펴볼 필요는 없지만, 혹시 관심이 있다면 참고할 수 있도록 여기에 포함되어 있습니다.
+
+•init.c, init.h
+커널 초기화 코드로, 커널의 메인 프로그램인 main()을 포함합니다. 적어도 main()을 살펴보아 어떤 초기화가 이루어지는지 확인하십시오. 필요하다면 여기에 여러분만의 초기화 코드를 추가할 수도 있습니다.
+
+•thread.c, thread.h
+기본적인 스레드 지원을 제공합니다. 여러분의 작업 대부분은 이 파일에서 이루어질 것입니다. thread.h는 구조체 스레드를 정의하며, 이는 네 가지 프로젝트 모두에서 수정하게 될 가능성이 높습니다. 자세한 내용은 Threads 섹션을 참고하십시오.
+
+•palloc.c, palloc.h
+페이지 할당기로, 4 kB 페이지 단위로 시스템 메모리를 할당합니다. 자세한 내용은 Page Allocator를 참고하십시오.
+
+•malloc.c, malloc.h
+커널용 malloc()과 free()의 간단한 구현입니다. 자세한 내용은 Block Allocator를 참고하십시오.
+
+•interrupt.c, interrupt.h
+기본적인 인터럽트 처리 및 인터럽트를 켜고 끄는 함수들을 제공합니다.
+
+•intr-stubs.S, intr-stubs.h
+낮은 레벨 인터럽트 처리를 위한 어셈블리 코드입니다.
+
+•synch.c, synch.h
+기본 동기화 도구: 세마포어(semaphores), 락(locks), 조건 변수(condition variables), 최적화 배리어(optimization barriers). 이들은 네 가지 프로젝트 모두에서 동기화를 위해 사용해야 합니다. 자세한 내용은 Synchronization을 참고하십시오.
+
+•mmu.c, mmu.h
+x86-64 페이지 테이블 작업을 위한 함수입니다. lab1 이후에 이 파일을 자세히 살펴보게 될 것입니다.
+
+•io.h
+I/O 포트 접근을 위한 함수들입니다. 주로 devices 디렉토리의 소스 코드에서 사용되며, 여러분은 이 코드를 수정할 필요가 없습니다.
+
+•vaddr.h, pte.h
+가상 주소 및 페이지 테이블 항목을 다루기 위한 함수와 매크로입니다. 프로젝트 3에서 더 중요해질 내용이므로, 지금은 신경쓰지 않아도 괜찮습니다.
+
+•flags.h
+x86-64 플래그 레지스터의 몇 가지 비트를 정의하는 매크로입니다. 거의 신경쓰지 않아도 됩니다.
+
+# devices 코드
+
+기본 스레드 기반 커널에는 devices 디렉토리에 다음 파일들도 포함됩니다:
+
+•timer.c, timer.h
+시스템 타이머로, 기본적으로 초당 100번 ticks을 생성합니다. 이 프로젝트에서 이 코드를 수정해야 합니다.
+
+•vga.c, vga.h
+VGA 디스플레이 드라이버. 화면에 텍스트를 출력하는 역할을 합니다. 이 코드를 직접 볼 필요는 없습니다. printf() 함수가 VGA 디스플레이 드라이버를 호출하므로, 이 코드를 직접 호출할 이유는 거의 없습니다.
+
+•serial.c, serial.h
+직렬 포트 드라이버. printf()가 이 코드를 대신 호출하므로, 직접 호출할 필요는 없습니다. 이 코드는 직렬 입력을 처리하며, 이를 입력 계층(아래 참조)에 전달합니다.
+
+•block.c, block.h
+블록 디바이스를 위한 추상화 계층으로, 고정 크기 블록 배열로 구성된 랜덤 액세스 디스크 유사 장치입니다. Pintos는 기본적으로 두 가지 유형의 블록 디바이스: IDE 디스크와 파티션을 지원합니다. 블록 디바이스는 프로젝트 2까지는 실제로 사용되지 않습니다.
+
+•ide.c, ide.h
+최대 4개의 IDE 디스크에서 섹터를 읽고 쓰는 것을 지원합니다.
+
+•partition.c, partition.h
+디스크의 파티션 구조를 이해하여 하나의 디스크를 여러 독립적인 영역(파티션)으로 나눌 수 있도록 합니다.
+
+•kbd.c, kbd.h
+키보드 드라이버. 키 입력을 처리하고 이를 입력 계층(아래 참조)으로 전달합니다.
+
+•input.c, input.h
+입력 계층. 키보드나 직렬 드라이버에서 전달된 입력 문자를 큐에 저장합니다.
+
+•intq.c, intq.h
+인터럽트 큐로, 커널 스레드와 인터럽트 핸들러가 모두 접근하고자 하는 순환 큐를 관리합니다. 키보드와 직렬 드라이버에서 사용됩니다.
+
+•rtc.c, rtc.h
+실시간 시계 드라이버로, 커널이 현재 날짜와 시간을 확인할 수 있도록 합니다. 기본적으로, 이는 thread/init.c에서 난수 생성기의 초기 시드를 선택하기 위해 사용됩니다.
+
+•speaker.c, speaker.h
+PC 스피커에서 톤을 생성할 수 있는 드라이버입니다.
+
+•pit.c, pit.h
+8254 프로그래밍 가능 인터럽트 타이머(PIT)를 구성하는 코드입니다. 이 코드는 각 디바이스가 PIT의 출력 채널 중 하나를 사용하기 때문에 devices/timer.c와 devices/speaker.c 모두에서 사용됩니다.
+
+# lib 코드
+
+마지막으로 lib와 lib/kernel에는 유용한 라이브러리 루틴이 들어 있습니다. (lib/user는 프로젝트 2부터 사용자 프로그램에서 사용되지만 커널의 일부는 아닙니다.) 다음은 몇 가지 자세한 내용 입니다:
+
+•ctype.h, inttypes.h, limits.h, stdarg.h, stdbool.h, stddef.h, stdint.h, stdio.c, stdio.h, stdlib.c, stdlib.h, string.c, string.h
+표준 C 라이브러리의 하위 집합입니다.
+
+•debug.c, debug.h
+디버깅을 돕는 함수와 매크로입니다. 자세한 내용은 디버깅 도구를 참조하세요.
+
+•random.c, random.h
+의사난수 생성기(pseudorandom number generator, PRNG)입니다. 실제 난수 값의 시퀀스는 Pintos 실행마다 다르지 않습니다.
+
+•round.h
+반올림을 위한 매크로입니다.
+
+•syscall-nr.h
+시스템 호출 번호입니다. 프로젝트 2까지는 사용되지 않습니다.
+
+•kernel/list.c, kernel/list.h
+이중 연결 리스트 구현입니다. Pintos 코드 전반에 사용되며, 프로젝트 1에서 직접 사용하게 될 것입니다. 시작하기 전에 이 코드를 훑어보는 것이 좋습니다(특히 헤더 파일의 주석).
+
+•kernel/bitmap.c, kernel/bitmap.h
+비트맵 구현. 원한다면 코드에서 사용할 수 있지만, 프로젝트 1에서는 필요하지 않을 것입니다.
+
+•kernel/hash.c, kernel/hash.h
+해시 테이블 구현. 프로젝트 3에 유용할 것 같습니다.
+
+•kernel/console.c, kernel/console.h, kernel/stdio.h
+printf() 및 몇 가지 다른 함수를 구현합니다.
+
+## 동기화
+
+적절한 동기화는 이러한 문제를 해결하는 데 중요한 부분입니다. 모든 동기화 문제는 인터럽트를 끄면 쉽게 해결할 수 있습니다. 인터럽트가 꺼져 있는 동안에는 동시성이 없어지므로 경쟁상태(Race Condition)가 될 가능성이 없습니다. 모든 동기화 문제를 이런 방식으로 해결하고 싶지만 그렇게 하면 안됩니다. 대신 세마포어, 락(locks) 및 조건 변수를 사용하여 대부분의 동기화 문제를 해결하세요. 동기화에 대한 투어 섹션(동기화 참조)이나 어떤 상황에서 어떤 동기화 기본 요소를 사용할 수 있는지 확실하지 않은 경우 threads/synch.c의 주석을 읽어보세요.
+
+Pintos 프로젝트에서 인터럽트를 비활성화하여 가장 잘 해결할 수 있는 유일한 문제는 커널 스레드와 인터럽트 핸들러 간에 공유되는 데이터를 조정하는 것입니다. 인터럽트 핸들러는 sleep 호출을 할수 없으므로 락을 얻을 수 없습니다. 즉, 커널 스레드와 인터럽트 핸들러 간에 공유되는 데이터는 인터럽트를 비활성화 하여 커널 스레드 내에서 보호해야 합니다.
+
+이 프로젝트는 인터럽트 핸들러에서 약간의 스레드 상태에만 액세스하면 됩니다. 알람 클락(Alarm Clock)의 경우 타이머 인터럽트는 sleep 상태의 스레드를 깨워야 합니다. 고급 스케줄러에서 타이머 인터럽트는 몇 가지 전역 및 스레드별 변수에 액세스해야 합니다. 커널 스레드에서 이러한 변수에 액세스하는 경우 타이머 인터럽트의 간섭을 막기 위하여 인터럽트를 비활성화해야 합니다.
+
+인터럽트를 끄는 경우 가능한 한 최소한의 코드에 대해서만 끄도록 주의하세요. 그렇지 않으면 타이머 틱이나 input 이벤트와 같은 중요한 항목을 잃을 수 있습니다. 인터럽트를 끄면 인터럽트 처리 지연 시간도 늘어나기에 머신이 느리게 느껴질 수 있습니다.
+
+synch.c의 동기화 기본 요소 자체는 인터럽트를 비활성화하여 구현됩니다. 여기서 인터럽트가 비활성화된 상태에서 실행되는 코드 양을 늘려야 할 수도 있지만, 최소한으로 유지하도록 노력하세요.
+
+인터럽트를 비활성화하면 디버깅에 유용할 수 있습니다. 코드 섹션이 중단되지 않도록 해야 하기 때문입니다. 프로젝트를 제출하기 전에 디버깅 코드를 제거해야 합니다. (단순히 주석으로 처리하지 마세요. 코드의 가독성이 떨어집니다.)
+
+제출 시 바쁜 대기(busy waiting)가 없어야 합니다. thread_yield()를 호출하는 타이트 루프는 바쁜 대기의 한 형태입니다.
+
+## 개발 제안
+
+과거에는 많은 그룹이 과제를 여러 부분으로 나누고, 각 그룹원이 마감일 직전까지 각자의 작업을 한 다음, 그때 그룹이 다시 모여 코드를 결합하고 제출했습니다. 이는 좋지 않은 방법입니다. 이 방법은 권장하지 않습니다. 이렇게 하는 그룹은 종종 두 가지 변경 사항이 서로 충돌하여 마지막에 많은 디버깅이 필요합니다. 이렇게 한 그룹 중 일부는 컴파일이나 부팅조차 되지 않은 코드를 제출하여 테스트를 통과하지 못했습니다.
+
+대신 git과 같은 소스 코드 제어 시스템을 사용하여 팀의 변경 사항을 일찍 자주 통합하는 것이 좋습니다. 이렇게 하면 모든 사람이 다른 사람의 코드를 완성된 시점이 아니라 작성된 대로 볼 수 있으므로 당황할 상황이 줄어듭니다. 이러한 시스템을 사용하면 변경 사항을 검토하고 변경 사항으로 인해 버그가 발생하면 작동되던 이전 버전으로 돌아갈 수도 있습니다.
+
+이 프로젝트와 후속 프로젝트를 진행하는 동안 이해하지 못하는 버그가 발생할거라 생각해야 합니다. 그럴 때, 디버깅 도구에 대한 부록을 다시 읽어보세요. 여기에는 속도를 높이는 데 도움이 되는 유용한 디버깅 팁이 많습니다(디버깅 도구 참조). 모든 커널 패닉이나 어설션 실패 시 해결하는 데 도움이 될 백트레이스에 대한 섹션을 꼭 읽어보세요(백트레이스 참조).