운영체제 개요
운영체제의 역할
- Program execution
- Access to computer resources (I/O device, Data…)
- Error detection and response
- Accounting (ex: task manager)
운영체제의 발전
-
Serial Processing : No OS, No Job scheduling
-
Simple batch system
- OS가 job을 할당
- Controlled by monitor
-
Uni-programming
- 다 실행될때까지 기다림
- bad utilization
-
Multiprogramming
- The processor can switch to the other job
- better utilization, needs more memory
-
Time sharing
- proceess에게 정해진 time slice (time quantum)가 주어진다.
- better utilization, bad throughput
-
Symmetric multiprocessing (SMP)
- 여러 processors가 main memory, I/O 장치들을 공유
- 여러 processors가 동일한 function 수행 가능
운영체제의 구성 요소
- Distributed Systems (분산시스템)
- 여러 컴퓨터를 연결해 사용
- 빠른 속도, 높은 데이터 가용성
- Command-Interpreter System
- user가 직접 OS에게 일을 시킨다
OS Architecture
- Monolithic kernel
- 모든 OS의 기능을 하나의 kernel이 가지고 있는다
- 하나 수정하면 전체를 컴파일 해야 한다
- Microkernel kernel
- kernel 내에 필요한 기능
Address space management, Interprocess communication, 기본적인 프로세스 scheduling 기능
- kernel간 통신속도가 느리다
- kernel 내에 필요한 기능
Process
Process란
- 컴퓨터에서 실행 중인 객체
- register 중 PC가 context를 가리킨다
- Context는 data와 code로 구성
Trace of Processes
- A -> time out -> B -> I/O request -> A
- 사이사이에 dispatcher가 processor에 process를 교체한다
Process state model
- Process suspension의 이유
- Swapping : memory 공간 확보를 위해
- Timing : 주기적으로 실행되는 프로그램
- Interactive user request : user의 요청
- Parent process request : parent process의 요청
Process Control block
- 구성요소 : Identifier, State, Priority, PC, Memory pointers, Address of memory context, I/O state info, Accounting info
- Process 1개 당 PCB 1개
Process Context
- User Context : code, data, user stack
- System Context : kernel stack, PCB
Virtual Address Space
프로세스가 실행되면 서 접근(access, reference) 가능한 주소들의 범위
-
32bit address computer : $2^{32}$ = 4G 번지, 3G~4G번지에는 커널이 들어간다
-
보조기억장치의 VAS는 프로세스 개수만큼 존재
-
구성
| kernel | stack (local var) | bss (만들때 초기화 안 한 global var) | data (만들때 초기화 한 global var) | code
Process Creation
-
Process가 생성되는 경우
- OS가 만드는 경우
- 실행 중인 process가 자식을 만드는 경우
- User command
-
fork()
- 자식 프로세스의 memory infotable이 부모의 context를 가리키게 한다
- memory내에서 부모의 data, stack을 복제한다
- 자식이 가리키는 것을 복제된 context로 바꾼다
- COW(Copy on write) : 복사를 늦춤으로서 메모리 절약
Process switch
- Mode change : Memory 내에서 user mode <-> system mode
- Context change : 다른 process로 switch
-
Context change를 하는 경우
- Process의 소멸 : Running -> Release
- Process의 block (I/O request, file open, page fault) : Running -> Blocked
- Expiration of time slice : Running -> Ready
- I/O interrupt : Blocked -> Ready
-
Steps of context switch
- Save context(pc, other register) of processor
- Update the PCB
- Move PCB to appropriate queue
- Select another process to execute
- Update the PCB
- Update memory-management data structures
- Restore context of the selected process
Process Termination
- Process가 삭제되는 경우
- Normal ompletion
- Parent request
- Protection error : 비정상적인 접근을 할때 OS가 강제 종료
- Arithmetic Error, Invalid instruction…
- terminated 상태 : Computer resource는 뺏겼지만, PCB는 남아있는 상태
- 해당 프로세서의 부모 프로세스가 wait syscall을 호출하면 완전히 삭제
- 지워지는 부모 밑에 자식이 남아있다면 자식들을 init 프로세스의 양자로 보낸다
Inter-Process Communication (IPC)
- Message Passing : kernel내 mailbox를 통해 메시지를 주고받는 방법
- user mode -> kernel mode -> user mode
- 구현이 쉽다, 느리다
- Shared Memory
- VAD에 shared memory법 주소를 갖고있다
- 빠르다, 구현이 어렵다
- Message / Signal
Threads
Process와 Thread의 차이
Thread란
-
A unit of execution of in a process
-
has an execution state
-
구성 요소
- Stack
- Memory for registers context : thread control block
-
multithread
Thread의 장점
- Process 만드는거 보다 Thread 만드는게 빠르다
- Process 없애는거 보다 Thread 없애는게 빠르다
- Process끼리 통신하는거보다 Thread끼리 통신이 더 빠르다 (data 공유)
User-Level Threads
- mode change가 필요없다
- user가 control 할 수 있다
- 하나가 block되면 나머지도 block (kernel 입장에서 1개의 thread)
Kernel-Level Threads
- kernel에 종속적이다
- kernel이 개별적으로 관리할 수 있다
Mutual Exclusion and Synchronization
Key terms in Concurrency
- Race condition : 순서에 따라 결과가 달라질 때
- Mutual exclusion : 한 프로세스가 공유된 data를 access할때, 다른 프로세스가 건드리면 안된다는 성질
- Critical section : 공유된 resource를 access하는 부분의 코드
- Starvation : Process에게 자원이 배정되지 않는 경우
- Deadlock : Starvation for infinite duration
Producer/Consumer : Finite Buffer
-
producer
1item v; 2 3 4while (1) { 5 while (counter == BUFFER_SIZE) ; // busy waiting 6 /* produce item v */ 7 b[in] = v; 8 in = (in + 1) % BUFFER_SIZE; 9 counter++; 10}
-
consumer
1item w; 2while (1) { 3 while (counter == 0) ; // busy waiting 4 w = b[out]; 5 out = (out + 1) % BUFFER_SIZE; 6 counter--; 7 /* consume item w */ 8}
-
=> Race condition 발생 가능
Race Condition in a Uniprocessor
- counter++, counter–와 같은 구문은 assembly로 바뀌면 1개이상의 instruction이다.
- 중간에 interrupt가 발생하면 race condition이 생길 수 있으므로 atomic하게 실행되어야한다.
Race Condition in one Process
- Multithreading에서도 race condition이 발생할 수 있다.
Prevent Race Condition (SW solution)
- 조건
- Mutual Exclusion : critical section에 하나가 접근 중이면 다른 하나는 접근 불가
- Progress : 아무도 없으면 접근 가능
- Bounded Waiting : 기다리는 데 한계 존재 (P1 -> P3 -> P1 -> P3 .., P2는?)
-
방법 1
- P0
1do { 2 while (turn != 0) ; 3 /* critical section */ 4 turn = 1; 5 /* remainder section */ 6} while (true);
- P1
1do { 2 while (turn != 1) ; 3 /* critical section */ 4 turn = 0; 5 /* remainder section */ 6} while (true);
- P0에서 turn = 1을 실행하기 전에 interrupt가 발생하면, P1도 접근 불가
- -> progress 성질 만족 X
- P0
-
방법 2 (Peterson’s Algorithm)
- P0
1do { 2 flag[0] = true; 3 turn = 1; 4 while (flag [1] && turn == 1) ; 5 /* critical section */ 6 flag[0] = false; 7 /* remainder section */ 8} while (true);
- P1
1do { 2 flag[1] = true; 3 turn = 0; 4 while (flag [0] && turn == 0) ; 5 /* critical section */ 6 flag[1] = false; 7 /* remainder section */ 8} while (true);
- 모든 조건 만족
- 프로세스 2개일때만 적용 가여
- P0
-
방법 3 (Bakery Algorithm)
1do { 2 // number를 부여받는 과정은 atomic 하지 않다 3 choosing[i] = true 4 // 가장 큰 번호 + 1을 부여 5 number[i] = max(number[0], number[1], ..., number[n-1])+1; 6 choosing[i] = false; 7 8 for (j=0; j<n; j++) { 9 // 다른 프로세스가 choosing 중인지 체크 10 while (choosing[i]); 11 12 // 자신이 번호를 받았는지, 발급 받은 번호가 1순위인지 체크 13 while ((number[i] != 0) && (number[j], j) < (number[i], i)) ; 14 } 15 16 /* critical section */ 17 18 number[i] = 0 19 20 /* remainder section */ 21 } while (true);
- 모든 조건을 만족
- Overhead가 너무 크다
Test and Set Instruction (HW solution)
- testset function
1boolean testset (i) { 2 if (i == 0) { 3 // 들어가시오 4 i = 1; 5 return true; 6 } 7 else { 8 // 들어가지 마시오 9 return false; 10 } 11}
- example
1const int n = /* number of processes */; 2int bolt; 3void P(int i) { 4 while (true) { 5 while (! testset(bolt)); 6 /* critical section */ 7 bolt = 0; 8 /* remainder section*/ 9 } 10} 11void main() { 12 bolt = 0; 13 parbegin (P(1), P(2), ... , P(n)) 14}
Semaphore (HW solution)
-
기본 요소
1struct semaphore { 2 int count; 3 queueType queue; 4} 5 6void semWait (semaphore s) { 7 s.count --; 8 if (s.count < 0) { 9 // place this process in s.queue; 10 // block this process 11 } 12} 13 14void semSignal (semaphore s) { 15 s.count++; 16 if (s.count <= 0) { 17 // remove a process P from s.queue; 18 // place process P on ready_list 19 } 20}
- basic example
-
1const int n = /* number of processes */ 2semaphore s = 1; 3void P (int i) { 4 while (true) { 5 semWait(s); 6 /* critical section */ 7 semSignal(s); 8 /* remainder section */ 9 } 10} 11void main() { 12 parbegin (P(1), P(2), ... , P(n)); 13}
-
producer/consumer example
- producer
1semaphore count = 0; 2semaphore empty = BUFFER_SIZE; 3semaphore mut_ex = 1; 4void producer() { 5 while (true) { 6 produce(); 7 semWait(empty); 8 semWait(mut_ex); 9 append(); // put the produced item into buffer 10 semSignal(mut_ex); 11 semSignal(counter); 12 } 13}
-
consumer
1void consumer() { 2 while (true) { 3 semWait(counter): 4 semWait(mut_ex); 5 take(); 6 semSignal(mut_ex); 7 semSignal(empty); 8 consume(); 9 } 10} 11void main() { 12 parbegin (producer1, producer2, ... , consumer); 13}
- producer
-
reader/writer example
-
writer process
1 void writer() { 2 while(true) { 3 semWait(wsem); 4 WRITEUNIT(); 5 semSignal(wsem); 6 } 7 }
-
reader process
1 void reader() { 2 while (true) { 3 semWait(rsem); // 다른 reader 접근 불가 4 readcount++; 5 if (readcount == 1) // 첫번째 들어가는 reader 6 semWait(wsem) // writer 접근 불능 7 semSignal(rsem); // 다른 reader 접근 가능 8 9 READUNIT(); 10 11 semWait(rsem); // 다른 reader 접근 불가 12 readcount--; 13 if (readcount == 0) // 마지막 나오는 reader 14 semSignal(wsem); // writer 접근 가능 15 semSignal(rsem); // 다른 reader 접근 가능 16 } 17 }
-
- binary semaphore
- semaphore의 값이 0과 1로 제한
- 값이 1로 바뀌었을 때,모든 프로세스가 ready state로 변환
-
Lock
- binary semaphore를 이용해 구현된 동기화 방식
Deadlock
Deadlock이란
- Starvation : 어떤 자원을 다른 프로세스가 이미 점유하고 있어서 실행할 수 없는 상황
- Deadlock : 2개 이상의 process들이 서로 starvation인 상태
Deadlock의 조건을 하나씩 깨보자
- Mutual exclusion : OS의 필수 기능
- Hold and wait : 시작부터 모든 자원을 받도록 구현 -> 비효율적
- No Preemption : 자원을 서로 뺏어감 -> 비효율적
- Circular Wait : 자원을 먼저 받아야 하는 경우 존재
해결방법
- 최선의 방법 : deadlock이 발생했을 때, 한 개씩 죽여보기
File Management
FCB
- File Control block, 보조기억장치에 저장
- 구성
file name, file size, uid, gid, file operation, creation time, last modified, last access time, address of file data…
Device file
- 블록형 파일 (단위 : 4096byte)
- file size 대신 major number, minor number 존재
- Device I/O가 발생하면 해당 Device File과 I/O 하듯이 작동