Skip to content

Commit 1bc354a

Browse files
authored
Merge pull request #66 from java-squid/sigrid
운영체제 12회
2 parents 6acc8a7 + 6d3442c commit 1bc354a

2 files changed

Lines changed: 190 additions & 0 deletions

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Context-Switch란 무엇인가?
2+
## 정의
3+
* Running 상태에 있는 프로세스 또는 쓰레드가 사용하는 Context(각 Task가 사용하는 CPU 레지스터의 값)을 메모리의 특정 영역에 저장한 후, 새롭게 수행할 Task의 Context를 TCB 또는 Stack에서 CPU의 레지스터 영역으로 복사하여 새로운 Task가 수행되도록 하는 일련의 작업을 의미한다.
4+
5+
## Context란 무엇인가?
6+
* Context: 각 Task가 사용하는 CPU 레지스터의 값이다.
7+
* 만약 프로세스라면?
8+
* 텍스트(Text) 영역 : 프로그램의 코드 부분
9+
* 데이터(Data) 영역 : 프로그램의 전역 변수 부분
10+
* 스택(Stack) 영역 : 프로그램의 지역 변수 부분
11+
* 힙(Heap) 영역 : 프로세스의 동적 메모리 할당 영역
12+
13+
* 커널 관리의 프로세스 관련 정보(태스크 구조체, task_struct)
14+
* 중앙 처리기 범용 레지스터의 내용: 일반적 계산을 위해 활용되는 레지스터들의 내용
15+
* 중앙 처리기 특수 레지스터의 내용: 프로세스의 실행 위치를 나타내는 프로그램 계수기(Program Counter)
16+
* 스택 포인터(Stack Pointer), 중앙 처리기 상태 레지스터, 가상 메모리 페이지 테이블 관련 정보 등
17+
* 프로세스 및 프로세스 그룹 식별자
18+
* 사용자 정보, 보안 정보 - 오픈 파일 정보
19+
* 프로세스 상태 - 시그널(Signal) 정보
20+
* 우선순위, 정책 등의 스케줄링 정보
21+
* 부모, 형제, 자식 프로세스 정보 - 타이머(Timer) 정보
22+
* 메모리 영역 정보 -
23+
* IPC(Inter-process Communication) 관련 정보
24+
25+
* Context 구성에서, 프로세스 공간 영역은 메모리에 할당되므로 프로세스 사용자 공간이 유지되면 자동 보존된다. 쓰레드 공간 영역은 같은 프로세스 내 공유하므로 자동 보존된다. 아마 함수 호출의 최소 단위로서 스레드의 정의에 따라 독립적인 실행 흐름을 추가하기 위한 최소 조건으로 독립된 스택을 할당하는 것이다. PCB 레지스터는 쓰레드가 CPU를 할당받았다가 스케쥴러에 의해 다시 선점당하기 때문에 명령어가 연속적으로 수행되지 못하고 어느 부분까지 수행했는지 기억할 필요가 있다. 따라서 쓰레드도 PC 레지스터를 독립적으로 할당받는다.
26+
* 프로세스 정보와 관련된 모든 문맥은 태스크 구조체(PCB, Process Control Block)에 위 표와 같이 보관되는데, 이들 중 프로세스 중단 시점에서 반드시 보존되고 실행 개시 시점에 복원되어야 하는 것은 대부분 중앙 처리기 레지스터들의 내용이다.
27+
* 즉, 레지스터들의 내용은 중앙 처리기를 차지하는 프로세스가 실행되는 동안 모두 변화되기 때문에, 프로세스 중지 시에는 반드시 보존되었다가 수행 속개 시 다시 복원되어야 한다.
28+
* 리눅스에서 커널의 프로세스 관리 정보를 담은 구조체(PCB)를 task_struct라고 한다. 프로세스가 실행 중 또는 준비 상태일 때는 CPU 별로 할당된 스케줄 큐인 runQueues에서 Linkedlist 형태로 저장된다. 대기 상태일 때는 스케줄링 큐에서 제거되어 대기별 큐(sleep queue)에 속한다.
29+
30+
![](https://i.imgur.com/fkDRqxm.png)
31+
* PCB의 저장 정보는 다음과 같다.
32+
* 프로세스 상태 : 신규, 준비, 수행, 대기, 정지
33+
* 프로그램 카운터 : 프로세스가 다음에 실행할 명령어 주소
34+
* 레지스터 : 누산기, 스택, 색인 레지스터
35+
* 프로세스 번호
36+
37+
## 스케줄링 기법
38+
* Dispatching
39+
* Ready 상태의 프로세스 또는 쓰레드 중에서 우선순위가 가장 높은 프로세스에 CPU 할당
40+
* Time Quantum
41+
* 특정 프로세스 또는 쓰레드에 할당되는 시간의 단위를 설정하여, 특정 프로세스 또는 쓰레드의 CPU 독점을 방지
42+
* Preemption
43+
* Time Quantum이 초과하면 인터럽트를 통해 CPU 사용권을 빼앗는 스케줄링 기법
44+
45+
## Context-Switch의 진행 과정
46+
### 진행 시점
47+
![](https://i.imgur.com/qwaMHjm.png)
48+
* 비자발적 문맥교환 (현 프로세스나 쓰레드가 원치 않은데 커널에 따라 강제로 교환당하는 경우)
49+
* 인터럽트의 처리 및 시스템 호출 완료 직후 사용자 모드로의 복귀 이전에 스케줄러가 수행되며 이 때 우선 순위가 현재 프로세스 보다 높은 프로세스가 있으면 비자발적 문맥 교환(involuntary context switch)이 일어난다.
50+
* 현 프로세스의 타임 슬라이스가 다 소진된 경우도 클럭 인터럽트 처리 과정에서 이러한 사실을 알게 되고, 이때에도 인터럽트 처리를 마치고 사용자 모드로 복귀하는 과정에서 문맥 교환이 발생한다.
51+
* 타임 슬라이스(Time Slice) 소진 시, 인터럽트(Interrupt) 발생 시
52+
* 자발적 문맥교환
53+
* 프로세스 자신이 잠들 때(Sleep)
54+
* 프로세스가 Exit 할 때
55+
* 시스템 호출로부터 사용자 모드로 돌아왔으나 실행될 가장 적당한 프로세스가 아닐 때(wait)
56+
* 커널이 인터럽트 처리를 마치고 프로세스가 사용자 모드로 돌아왔으나 실행될 가장 적당한 프로세스가 아닐 때 (wait)
57+
58+
### 진행과정
59+
![](https://i.imgur.com/C2ZcfhF.png)
60+
```
61+
① Interrupt나 시스템 호출에 의해 문맥 교환 요구
62+
63+
② 사용자 Mode -> 운영체제 모드
64+
65+
③ 기존 프로세스의 현재 H/W 상태정보를 PCB에 저장 (PCB: Process Control Block)
66+
67+
④ 다음에 실행할 프로세스의 상태정보를 PCB에서 복구한 후 다음 프로세스를 실행함
68+
69+
⑤ 운영체제 모드 -> 사용자 Mode로 전환
70+
```
71+
* Context-Switching 과정에서 발생하는 오버헤드
72+
* 1단계: 현 프로세스
73+
* 2단계: Interrupt 처리 루틴
74+
* 현재 상태를 PCB에 저장하는 오버헤드
75+
* 3단계: 프로세스 스케쥴러
76+
* 다음 실행 프로세스를 준비 Queue에서 선택
77+
* 4단계: Dispatch
78+
* 다음 Process의 PCB값 복구
79+
* 5단계: 다음 프로세스 지정
80+
* 해결 방안:
81+
* Context Switch 자주 발생하지 않도록 다중 프로그래밍의 정도를 낮춤
82+
* 스택 중심의 장비에서는 Stack 포인터 레지스터를 변경하여 프로세스간 문맥교환 수행
83+
* Light Weight Process인 스레드를 이용하여 Context Switch 부하를 최소화시킴
84+
85+
## 쓰레드 중심의 Context-Switching은 어떨까?
86+
### 의의
87+
* 스레드는 실행에 필요한 최소한의 정보만을 가지고 자신이 속해 있는 프로세스의 기억장치나 파일과 같은 실행환경을 공유하여 프로세스의 생성과 문맥교환 등의 오버헤드를 줄일 수 있다.
88+
* 병행성 증진: 단일 프로세스에서 다수의 스레드 생성 및 수행
89+
* 오버헤드 감소: 실행 환경의 공유를 통해 오버헤드 줄임
90+
### 실행 절차
91+
![](https://i.imgur.com/SfjYQ12.png)
92+
* CPU 내에 존재하는 레지스터들은 현재 실행 중인 프로세스 관련 데이터들로 채워짐(T0) (실행 중인 프로세스가 변경되면, CPU 내에 존재하는 레지스터들의 값이 변경되어야 함)
93+
* 프로세스 T1이 실행되기 전에, 현재 T0 레지스터들이 지니고 있는 데이터들을 저장
94+
* 프로세스 T1은 Ready 상태로 바뀌고, 프로세스 T1와 관련된 메모리에 백업된 레지스터 정보를 Restore하여 수행
95+
* 프로세스 T1은 마지막 실행 이후를 이어서 실행
96+
* 프로세스 T0 관련 레지스터 정보는 메모리에 저장되고, 프로세스 T1 관련 레지스터 정보는 CPU의 레지스터에 복원
97+
98+
### 참고: 언제 Interrupt가 이루어질까?
99+
* I/O request (입출력 요청할 때)
100+
* time slice expired (CPU 사용시간이 만료 되었을 때)
101+
* fork a child (자식 프로세스를 만들 때)
102+
* wait for an interrupt (인터럽트 처리를 기다릴 때)
103+
104+
### Reference
105+
* http://jidum.com/jidums/view.do?jidumId=442
106+
* https://jeongchul.tistory.com/94
107+
* https://jeong-pro.tistory.com/93
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# 데드락이란 무엇인가
2+
## 정의
3+
* 운영체제에서 데드락이란, 시스템 자원에 대한 요구가 엇갈린 상태를 의미한다.
4+
* 둘 이상의 프로세스가 다른 자원의 프로세스를 점유하다보니, 무한 대기(루프) 상태에 빠지게 되는 것을 의미한다.
5+
* 즉, Deadlock은 다른 프로세스 또는 쓰레드가 소유한 자원을 요청한 행위가 서로에게 행해져 모든 프로세스 또는 쓰레드가 block이 되는 상태를 의미한다.
6+
* A lock occurs when multiple processes try to access the same resource at the same time.
7+
* One process loses out and must wait for the other to finish.
8+
* A deadlock occurs when the waiting process is still holding on to another resource that the first needs before it can finish.
9+
## 예시 1
10+
![](https://i.imgur.com/MEXzKoF.png)
11+
* 쓰레드 T0이 리소스 1에 대한 Lock이 걸려 있는 상태이지만, 해당 쓰레드가 모든 일을 끝마치려면 리소스 2에 대한 자원이 필요한 상태이다.
12+
* 쓰레드 T1이 리소스 2에 대한 Lock이 걸려 있는 상태이지만, 해당 쓰레드가 모든 일을 끝마치려면 리소스 1에 대한 자원이 필요한 상태이다.
13+
## 예시 2
14+
### 서로가 사용하고 있는 Semaphore를 요청하여 Block에 걸리게 되는 경우
15+
* 다음과 같이 두 개의 코드가 주어졌다고 생각하자.
16+
```
17+
Process1
18+
owns lock A
19+
requests lock B
20+
```
21+
```
22+
Process2
23+
owns lock B
24+
requests lock A
25+
```
26+
* 여기서 프로세스 1은 lock A를 갖고 있는데, 이는 A에 대한 세마포어(semaphore)를 갖고 있다는 뜻이다. 이와 달리, 프로세스 2는 lock B를 갖고 있는데, 이는 B에 대한 세마포어(semaphore)를 갖고 있다는 뜻이다.
27+
* 세마포어는 한 곳에서 사용 중이라면, 다른 프로세스를 차단하는 목적으로 사용된다. 프로세스 1이 lock B를 요청할 경우, lock B는 현재 사용 중이므로 프로세스 1은 lock B가 release되기 전까지 Block 상태에서 대기하게 된다.
28+
* 프로세스 2도 마찬가지이다. lock A를 요청할 경우, 현재 lock A는 사용 중이므로 프로세스 2는 lock A가 release되기 전까지 Block 상태에서 대기하게 된다.
29+
![](https://i.imgur.com/n86eluU.png)
30+
## 예시 3
31+
### Recursive Lock
32+
* 프로세스 1이 한 semaphore를 갖고 있다. 해당 semaphore는 다른 프로세스가 접근할 수 없게 된다. 이 떄, 프로세스 1은 똑같은 semaphore에 접근을 요청한다. 이러한 경우, 해당 semaphore는 접근할 수 없음으로 데드락에 빠지게 된다.
33+
![](https://i.imgur.com/a6f89wO.png)
34+
## 예시 4
35+
### 범죄자와 경찰
36+
![](https://i.imgur.com/lWTXmAi.png)
37+
* Imagine a criminal holds an hostage and against that, a cop also holds an hostage who is a friend of the criminal. In this case, criminal is not going to let the hostage go if cop won't let his friend to let go. Also the cop is not going to let the friend of criminal let go, unless the criminal releases the hostage. This is an endless untrustworthy situation, because both sides are insisting the first step from each other.
38+
* So simply, when two threads needs two different resources and each of them has the lock of the resource that the other need, it is a deadlock.
39+
40+
## Deadlock의 상태
41+
* 일반적으로 프로세스는 리소스를 사용하기 위해서는 사전에 요청을 거쳐야 하고, 다음과 같은 과정을 거친다.
42+
* Request: 리소스 사용을 요청할 때 즉각 받아들여지지 않는다면, 프로세스는 리소스 사용이 가능해질 때까지 대기해야 한다. 주된 함수 연산으로는 ```call(), malloc()``` 등이 있다.
43+
* Use: 쓰레드가 자원을 사용하는 단계이다. 프린터를 사용하고 있거나, 파일을 읽고 있다.
44+
* Release: 프로세스는 리소스 사용을 중지(relinquish)한다. 따라서 해당 자원은 다른 프로세스가 사용 가능해진다. 주된 함수 연산으로는 ```close(), free(), delete()``` 등이 있다.
45+
* 커널이 매니징하느냐? 애플리케이션이 매니징하느냐? 에 따라 차이가 있는데 아무래도 커널이 관리해주는 것이 개발자 입장에서는 불필요한 소요를 줄이는 일이지 않을까 싶다.
46+
* 커널이 매니징한다는 것은, 커널이 어떤 리소스가 free이고 어디에 allocate 되어 있고를 모두 파악한다는 소리다. 현재 process의 queue를 관리해서 어느 프로세스가 다음 리소스의 사용을 원하는 지를 확인한다.
47+
* Application이 매니징한다는 것은, mutex나 wait(), signal() 함수 호출로 인하여 컨트롤 되는 것을 의미한다.
48+
49+
## Deadlock의 4가지 조건
50+
* Mutual Exclusion: 최소 한 개의 리소스가 non-sharable한 상태로 특정한 프로세스나 쓰레드에 의해 사용되고 있어야 한다. 만약 다른 프로세스가 해당 리소스 사용 요청을 보내면, 해당 프로세스는 리소스가 사용 가능할 때까지 기다려야 한다.
51+
* Hold and Wait: 프로세스는 동시에 하나의 리소스를 갖고 있으면서 또 다른 프로세스나 쓰레드가 점유하고 있는 리소스 사용을 요청할 수 있다.
52+
* No Preemption: 임의의 프로세스가 리소스를 소유한다고 가정하자. 그렇다면 다른 프로세스나 쓰레드는 해당 프로세스나 쓰레드가 스스로 리소스를 내려 놓기 전까지는 강제로 끌어내릴 수 없다.
53+
* Circular wait: A set of processes { P0, P1, P2, . . ., PN } must exist such that every P[ i ] is waiting for P[ ( i + 1 ) % ( N + 1 ) ]. (해당 조건은 Hold and Wait 조건을 support하는 것 같다)
54+
55+
## 데드락, 어떻게 해결할 것인가
56+
## 데드락을 예방 Prevention 하기
57+
* Not allowing the system to get into a deadlocked state. 위의 4가지 조건을 모두 충족시키지 않으면서 가능하다.
58+
* 자원의 상호 배제 조건 방지 : 한 번에 여러 프로세스가 공유 자원을 사용할 수 있게 한다. 다만, 추후 동기화 문제가 생길 수 있다.
59+
* 점유 대기 조건 방지 : 프로세스 실행에 필요한 모든 자원을 한꺼번에 요구하고 허용할 때까지 작업을 보류해서, 나중에 또다른 자원을 점유하기 위한 대기 조건을 성립하지 않도록 한다.
60+
* 비선점 조건 방지 : 이미 다른 프로세스에게 할당된 자원이 선점권이 없다고 가정할 때, 높은 우선순위의 프로세스가 해당 자원을 선점할 수 있도록 합니다.
61+
* 순환 대기 조건 방지 : 자원을 순환 형태로 대기하지 않도록 일정한 한 쪽 방향으로만 자원을 요구할 수 있도록 합니다.
62+
* 데드락 예방(Prevention)은 시스템의 처리량이나 효율성을 떨어트리는 단점이 있다.
63+
64+
### 데드락 회피(avoidance)
65+
* 시스템의 프로세스들이 요청하는 모든 자원을, 데드락을 발생시키지 않으면서도 차례로 모두에게 할당해 줄 수 있다면 안정 상태(safe state)에 있다고 한다.
66+
* 그리고 이처럼 특정한 순서로 프로세스들에게 자원을 할당, 실행 및 종료 등의 작업을 할 때 데드락이 발생하지 않는 순서를 찾을 수 있다면, 그것을 안전 순서(safe sequence)라고 부른다.
67+
* 불안정 상태는 안정 상태가 아닌 상황을 말한다. 데드락 발생 가능성이 있는 상황이며, 교착 상태(데드락)는 불안정 상태일 때 발생할 수 있다.
68+
* 회피 알고리즘은 자원을 할당한 후에도 시스템이 항상 Safe state에 있을 수 있도록 할당을 허용하자는 것이 특징이다.
69+
* 은행원 알고리즘: 은행원 알고리즘의 경우, 이처럼 미리 최대 자원 요구량을 알아야 하고, 할당할 수 있는 자원 수가 일정해야 하는 등 사용에 있어 제약조건이 많고, 그에 따른 자원 이용도 하락 등의 문제가 있을 수 있다.
70+
71+
### 데드락 탐지 및 회복(Detection)
72+
* 탐지
73+
* Allocation, Request, Available 등으로 시스템에 데드락이 발생했는지 여부를 탐색
74+
* 현재 시스템의 자원 할당 상태를 파악
75+
* 회복
76+
* 순환 대기에서 벗어나 데드락으로부터 회복하기 위한 방법을 사용
77+
* 단순히 프로세스를 1개 이상 중단시키기: 상태에 빠진 모든 프로세스를 중단하거나, 프로세스를 하나씩 중단 시킬 때마다 탐지 알고리즘으로 데드락을 탐지하면서 회복시키는 방법: 매번 탐지 알고리즘을 호출 및 수행해야 하므로 부담이 되는 작업일 수 있음
78+
* 자원 선점하기: 프로세스에 할당된 자원을 선점해서, 교착 상태를 해결할 때까지 그 자원을 다른 프로세스에 할당해 주는 방법
79+
80+
#### Reference
81+
* 더 알아보기 좋은 자료(영문): https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/7_Deadlocks.html
82+
* https://stackoverflow.com/questions/34512/what-is-a-deadlock
83+
* https://chanhuiseok.github.io/posts/cs-2/

0 commit comments

Comments
 (0)