diff --git a/week2/.DS_Store b/week2/.DS_Store new file mode 100644 index 0000000..52dc50e Binary files /dev/null and b/week2/.DS_Store differ diff --git a/week2/chapter3_Process/echo.md b/week2/chapter3_Process/echo.md new file mode 100644 index 0000000..e84ce34 --- /dev/null +++ b/week2/chapter3_Process/echo.md @@ -0,0 +1,198 @@ +--- +createdAt: 2024-01-27 +updatedAt: 2024-01-27 +tags: + - OS +sourceType: Book +--- +프로세스: 실행 중인 프로그램 → 시스템에서 작업의 단위 + +# 프로세스 개념 + +작업, 사용자 프로그램, 또는 태스크 +현대에서는 프로세스 선호 + +## 프로세스 + +비공식적으로 프로세스는 실행 중인 프로그램 + +프로세스의 현재 활동의 상태를 **프로그램 카운터**와 프로세서 레지스터의 내용으로 나타냄 + +![[Chapter 3. Process 2024-01-27 09.41.20.excalidraw]] + +- Text: 실행 코드 +- Data: 전역 변수 +- Heap: 프로그램 실행 중에 동적으로 할당되는 메모리 +- Stack: 함수를 호출할 때 임시 데이터 저장소(매개변수, 복귀 주소 및 지역 변수) + + +- 텍스트 및 데이터 섹션 크기는 프로그램 실행 시간 동안 크기가 변하지 않음 +- 스택과 힙은 변함 +- 함수가 호출될 때마다 매개변수, 지역변수 , 복귀 주소를 포함하는 **활성화 레코드**가 스택에 푸시 된다. +- *이때 운영체제는 힙과 스택이 서로의 방향으로 겹치지 않도록 해야함* + +> 프로세스 != 프로그램 + +프로그램은 명령어 리스트를 내용으로 가진 디스크에 저장된 파일(실행 파일) - 수동적 존재 + +프로세스는 다음에 실행할 명령어를 지정하는 프로그램 카운터와 자원의 집합을 가짐 - 능동적 존재 + +예를 들어, 여러 브라우저 프로그램을 동시에 실행 시킬 수 있지만 각각 별도의 프로세스 + +### 프로세스 상태 + +프로세스는 실행되면서 **상태**가 변한다. +![[Screenshot 2024-01-27 at 10.38.56.png]] + +- new: 생성 +- running: 실행 +- waiting: 대기(입출력 완료, 신호 수신) +- ready: 처리기에 할당되기를 기다리는 중 +- terminated: 실행 종료 + +### 프로세스 제어 블록 +![[Screenshot 2024-01-27 at 10.41.04.png]] +Process Control Block, PCB + +- 상태 - 프로세스 상태 +- 카운터 - 다음 실행할 명령어의 주소 +- 레지스터 - 다양한 레지스터들과 상태코드, 프로그램 카운터와 함께 상태정보는 나중에 다시 스케줄 될 때 인터럽트 발생 시 저장 +- 메모리 관리 정보 - OS에 의해 사용되는 메모리 시스템에 따라 기준 레지스터와 한계 레지스터의 값, 페이지 테이블, 혹은 세그먼트 테이블과 같은 정보 포함 +- 회계 정보 - CPU 사용 시간, 경과 시간, 프로세스 번호 등등 +- 입출력 상태 정보 - 이 프로세스에 할당된 입출력 장치들과 열린 파일 목록 등 + +### 스레드 + +프로세스 개념을 확장해 한 프로세스가 여러 실행 스레드를 가지도록 허용 + +## 프로세스 스케줄링 + +- 프로세스 스케줄러는 코어에서 실행 가능한 여러 프로세스 중에서 하나의 프로세스를 선택 +- 현재 메모리에 있는 프로세스 수 = 다중 프로그래밍 정도 +- 대부분의 프로세스는 I/O 바운드 혹은 CPU 바운드 프로세스 + +### 스케줄링 큐 +- 프로세스가 시스템에 들어가면 준비 큐에 들어가 준비 상태 +- 이때 큐는 연결 리스트 +- 준비 큐 헤더에는 리스트의 첫 번째 PCB 포인터 저장 → 각 PCB에는 다음 PCB 포인터 필드 포함 + +준비 큐 외에도 다른 큐 존재 +- 프로세스에 CPU 코어가 할당되면 프로세스는 실행 후 종료, 인터럽트, I/O 요청완료 등 특정 이벤트 발생까지 기다림 +- 이때 프로세스가 기다리는데 이때 대기큐에 삽입 +![[Screenshot 2024-01-27 at 18.13.23.png]] + +![[Screenshot 2024-01-27 at 18.13.37.png]] + +### CPU 스케줄링 +- 역할: 준비 큐에 있는 프로세스 중 하나의 프로세스에 CPU 코어 할당 +- 새 프로세스 자주 선택해야함 +- 100 밀리초마다 실행 +- 일부 운영체제는 스와핑 형태의 스케줄링 보유 + - 메모리에서 프로세스를 제거해 다중 프로그래밍 정도 감소 + - 디스크로 스왑아웃 하면서 현재 상태 저장 → 스왑인하면서 복원 + +### 문맥 교환 + +- 인터럽트 발생하면 인터럽트가 끝난 후 문맥 복구할 수 있도록 저장해야함 +- 이때 문맥은 PCB에 표현 +- 어떤 모드이건 CPU 현재 상태를 저장하는 작업 수행 후 상태 복구 작업 수행 +- CPU를 다른 프로세스로 교환하는 작업도 문맥 교환 +- 운영체제가 복잡해지면 문맥 교환 작업도 많아짐 +![[Screenshot 2024-01-27 at 22.00.54.png]] + +## 프로세스 연산 + +- OS는 프로세스 생성 종료가 가능해야함 + +### 생성 + +- 생성 프로세스 = 부모 프로세스 +- 새로운 프로세스 = 자식 프로세스 +- 프로세스는 트리를 형성 +- PID를 통해 구별 +- 주로 systemd가 PID 1 프로세스 +- fork() 시스템 콜을 통해 생성 +- 그 다음 exec()를 통해 메모리 공간을 새로운 프로그램으로 교체 +- 자식 실행 동안 할 일 없으면 wait() + +생성 방식은 2가지 +1. 부모 자식 동시 실행 +2. 부모는 자식이 실행이 종료할 때가지 기다리기 + +주소공간으로는 +1. 자식 프로세스는 부모 프로세스의 복사본 +2. 자식 프로세스는 자신의 새로운 프로그램을 보유 + +### 종료 + +- 프로세스가 실행을 종료하면 exit 시스템 콜 → 운영체제에게 자신의 삭제 요청 +- 부모 프로세스에 wait을 통해 상태값을 반환 가능 +- 이때 모든 자원이 할당 해제되고 운영체제로 반납 + +- 자녀 PID를 통해 종료 가능 + - 부모에 할당된 자식이 자원을 초과할때 + - 자식 테스크가 필요 없을때 + - 부모가 종료될때 자식도 강제 종료됨 - 연쇄적 종료 +- 좀비 프로세스: 부모가 wait을 호출하지 않아서 프로세스 테이블에 남아있는 상태 +- 고아 프로세스: 부모 프로세스가 wait을 호출하지 않고 종료 + +## 프로세스간 통신 IPC + + +- 운영체제 내에서 프로세스는 독립적이거나 협력적 +- 협력적 + - 정보 공유: 정보에 병행 접근 가능 + - 계산 과속화: 서브 테스크로 나누어 병렬 처리 가능 + - 모듈성: 스레드 프로세스로 나누어 모듈 형태 구성 + +## 공유 메모리 + +- 통신하는 프로세스들이 공유 메모리 영역을 구축해야함 +- 공유 메모리 세그먼트를 생성하는 프로세스 주소 공간에 위치 +- 다른 프로세스 메모리에 접근 불가능한 OS 제약을 제거 했기 때문에 프로세스가 동일한 위치에 쓰지 않도록 해야하는 책임 주체 +- 공유 메모리 구축 과정에서만 시스템콜이 사용되기 때문에 빠름 + +## 메세지 전달 + +### 방식 + +- 직접 / 간접 +- 동시식 / 비동기식 +- 자동/ 명시적 버퍼링 + +## 직접 통신 (명명) + +- 하나의 연결이 존재해야함 +- 송,수신자의 이름을 명시 +- 송, 수신자 프로세스 모두 상대방 이름을 제시하는 대칭성, 하지만 비대칭 방식 변형 가능 + +### 간접 통신 + +- 메일 박스 혹은 포트로 송수신 +- 프로세스가 메일 박스로 메세지를 넣고 제거하는 방식 +- 고유 ID를 가짐 +- 다수 메일 박스를 통해 다른 프로세스와 통신 가능 +- 메일 박스는 운영체제 혹은 프로세스에 의해 생성 가능 +- 소유권, 수신 특권은 시스템 콜을 통해 다른 프로세스에 전달 가능 + + +## 동기화 + +- blocking send: 송신하는 프로세스는 수신자가 수신할때까지 봉쇄 +- blocking receive: 메세지가 이용 가능할때까지 수신자 봉쇄 +- non-blocking send: 송신하는 프로세스가 메세지 보내고 작업 이어서 +- non-blocking receive: 수신하는 프로세스가 null 수신 가능 + +### 버퍼링 + +- 통신하는 프로세스들에 의해 교환되는 메세지는 임시 큐에 들어감 +- 큐 구현 방식 +1. 무용량 큐: 큐 최대 길이 0, 메세지 가질 수 없음 +2. 유한 용량: n개의 메세지 수용 +3. 무한 용량: 무한 길이 가능 + +- 대기발생 + 1. 송신자는 메세지 수신까지 대기 + 2. 공간이 생길때까지 큐 봉쇄 + 3. 없음 + diff --git a/week2/chapter4_Threads&Concurrency/echo.md b/week2/chapter4_Threads&Concurrency/echo.md new file mode 100644 index 0000000..ff37d8e --- /dev/null +++ b/week2/chapter4_Threads&Concurrency/echo.md @@ -0,0 +1,157 @@ +--- +createdAt: 2024-01-27 +updatedAt: 2024-01-27 +tags: + - OS +sourceType: Book +--- +# 스레드와 동시성 + +- 스레드는 CPU 이용의 기본 단위 +- ID, PC, 레지스터 집합, 스택으로 이루어짐 +- 같은 프로세스의 스레드끼리 운영체제 자원 공유 + +## 동기 + +- 기존 프로세스와 새로 생성한 프로세스가 해야할 일이 같다면 만드는 것보다 스레드를 만드는게 효율적이라서 +## 다중 스레드 장점 + +- 응답성: 프로그램의 긴 작업 수행 및 봉쇄에도 프로그램 수행이 계속 되기 때문에 응답성 증가 +- 자원 공유: 프로세스는 별도의 전달 방식이 필요하지만 스레드는 자동 공유 +- 경제성: 스레드간 문맥 교환이 빠르고 생성 비용이 적다. +- 규모 적응성: 다중 처리 구조에서 스레드는 병렬로 처리 가능 +# 다중 코어 프로그래밍 + +- 여러 CPU 사용 +- 동시 시스템: 모든 작업이 진행되게 해 둘 이상의 작업 지원(시분할 시스템) +- 병렬 시스템: 실제로 둘 이상의 작업 동시 수행 + +## 도전과제 +- 테스크 인식: 동시 처리 가능한 테스크로 나눌 수 있는 영역 찾기 +- 균형: 각 작업이 균등하도록 테스크 나누기 +- 데이터 분리: 데이터도 독립적으로 관리 +- 데이터 종속성: 둘 이상의 테스크가 의존하지 않도록 +- 시험 및 디버깅: 다양한 실행 경로에서 테스트 디버깅 시행 + +## 병렬 실행 유형 + +1. 데이터 병렬 실행: 동일한 데이터 부분 집합을 다수 코어에 분배해 연산 +2. 테스크 병렬 실행: 테스크를 다수 코어에 분배해 연산을 실행 +![[Screenshot 2024-01-27 at 22.57.17.png]] + + +## 다중 스레드 모델 + +- 스레드는 사용자 스레드와 커널 스레드로 나누어짐 +- 사용자 스레드: 커널 위에서 지원, 커널 지원 없이 관리 +- 커널 스레드: OS 직접 지원 + +## 다대일 + +- 커널 스레드 1: 사용자 스레드 N +- 관리: 사용자 공간의 스레드 라이브러리 +- 단점: + - 한 스레드가 봉쇄형 시스템 콜을 할 경우 전체 프로세스 봉쇄 + - 한 번에 하나의 스레드만이 커널에 접근 → 멀티 코어에서 병렬 실행 X + - 그린 스레드가 이 방식 사용 + +## 일대일 + +- 커널 1: 사용자 1 +- 하나의 스레드가 봉쇄적 시스템 콜을 해도 다른 스레드 실행 +- 단점: + - 커널 스레드를 생성해야해서 시스템 성능 부담 + +## 다대다 + +- 커널 N: 사용자 M (N >= M) +- two-level model 사용 +- 동시에 1:1도 지원 + +# 스레드 라이브러리 + +프로그래머에게 스레드 생성 관리하기 위한 API 제공 + +- 사용자 공간 라이브러리: 시스템 콜이 아닌 사용자 공간에서 지역 함수 호출 +- 커널 수준 라이브러리: 커널 시스템 콜 + +생성법 +- 비동기 스레딩 + - 부모가 자식 스레드 생성 후 부모 실행 재개, 자식과 독립적으로 실행, 데이터 공유 거의 없음 +- 동기 스레딩 + - 자식 스레드가 종료되면 부모 스레드 실행, 데이터 공유할 수 있다. + +# 암묵적 스레딩 + +- 스레딩 생성 관리 책임을 컴파일러나 런타임 라이브러리가 가져감 + +## 스레드풀 + +- 스레드를 미리 만들어 스레드 풀로 만듬 +- 프로세스 시작시 일정 수 스레드로 풀 만들어 둠 + +- 순서 + - 유휴 스레드 + - 요청 들어오면 깨어남 + - 유휴 스레드가 없으면 생길때까지 대기 + +- 풀 개수는 코어수, 물리 메모리 용량, 요청 최대 개수 등으로 계산 + +## Fork Join + +- 부모 스레드가 자식 스레드 생성한 다음 자식의 종료를 기다리고 join +- 결과 확인하고 결합 가능 +- 동기 버전의 스레드 풀 방식 + +# 관련 문제들 + +## Fork Exec 시스템 콜 + +- 다중 스레드에서 프로세스를 생성하는 fork()를 호출할때 + - 새로운 프로세스는 한 개의 스레드만 가지는 프로세스? + - 아니면 모든 스레드를 복사한 프로세스? + - 몇몇 OS는 둘 다 제공 + - 만약 exec를 호출한다면 모든 스레드 복제는 불필요 + - exec 호출하지 않는다면 모든 스레드 복제 필요 + +## 신호 처리 + +- 어떤 이벤트가 일어났다는 것을 알려주기 위해 사용 +- 동기적 혹은 비동기적으로 전달 +- 어쨋든 처리해야함 + - 신호는 특정 이벤트가 일어나야 생성 + - 생성된 신호가 프로세스에 전달 + - 신호가 전달되면 반드시 처리 + +- 둘 처리기 중 하나에 의해 처리 + - 디폴트 + - 사용자 정의 +- 신호 전달 방식 + - 신호가 적용될 스레드에게 전달 + - 모든 스레드에게 전달 + - 몇몇 스레드들에만 선택적으로 전달 + - 특정 스레드가 모든 신호를 전달받도록 지정 + +### 스레드 취소 + +취소해야할 스레드 = 목적 스레드 + +- 비동기식 취소: 한 스레드가 즉시 목적 스레드 종료 +- 지연 취소: 목적 스레드가 주기적으로 자기 자신이 종료 되야하는지 점검 +### 스레드 로컬장치 TLS + +- 스레드들은 프로세스 데이터 공유하는데 자기만 엑세스 할 수 있는 데이터 필요 +- 이를 TLS +- 정적 데이터와 유사 +- 다만 스레드마다 고유 + +### 스케줄러 엑티베이션 + +- 다대다 또는 two - level model을 구현하는 시스템은 중간 자료 구조를 둠 +- 이를 경량 프로세스 혹은 LWP라고 부름 +- 하나의 커널 스레드에 부속되어있음 +- 스케줄 하는 대상은 해당 커널 스레드 +- 해당 커널 스레드 봉쇄 → 해당 커널 스레드의 LWP 봉쇄 → 해당 LWP에 부속된 사용자 스레드 봉쇄 + +- 사용자 스레드 라이브러리와 커널 스레드 통신 방법의 하나는 스케줄러 엑티베이션 +- 커널이 응용 프로그램에게 특정 이벤트를 알려주며 이를 upcall이라고 함 \ No newline at end of file