- OS란?
- OS Structure
- Process
- Process Scheduling
- Thread Concurrency
- Synchronization Tools
레지스터란 뭘까?
레지스터는 CPU가 요청을 처리하는데 필요한 데이터들을 일시적으로 기억하는 기억장치이다.
CPU는 자체적으로 데이터를 저장할 방법이 없기 때문에 레지스터가 필요하다.
우리는 데이터를 저장할 때, 영구적으로 기억하고 싶다면 하드디스크에 저장하고, 일시적으로 기억하고 싶다면 메모리(RAM)에 저장한다.
하지만 메모리에 있는 데이터를 하드디크스에 저장하기 위해서는 주소 공간이나 명령 등을 기억할 수 있는 기억 장치가 하나 더 필요한데, 그게 바로 레지스터이다.
레지스터는 공간은 작아도 CPU와 직접 연결되어 있어서 메모리보다 빠르다!
-> 실행중인 프로그램. job이라고도 함.
-> 어떤 특정한 프로세스 상태에서의 실행 흐름
↑ Memory ↑
이때! 1개의 program은 여러 개의 process가 될 수 있음!
ex) 구글이라는 program을 여러 개의 창(process)을 띄워놓고 사용하는 상황
멀티프로세싱을 하게 되면, OS는 각 프로세스에서 어떤 일을 하는 지 알 필요가 있다.
이것을 저장하는 것이 PCB로, 각 프로세스마다 1개 씩 PCB가 있다.
PCB가 저장하는 내용으로는,
process들이 실행되면, state가 바뀌게 됨.
이 state들을 다루기 위해 3개의 queue가 존재.
! state transition은 즉, 프로세스들의 queue들간 이동이다 !
이때, ready 큐에 누구를 넣을 지를 왜 고민할까? 그냥 다 때려 넣으면 되는 거 아닌가?
-> process는 두 가지 종류가 있음!
즉, 얘네를 어떻게 해야 효율적으로 CPU에 할당 할 수 있을 지를 잘 고려해서 ready 큐에 넣어준다.
여러 프로세스들이 CPU를 돌아가면서 점유하기 때문에, 밀려나는 프로세스의 상태는 저장하고 새로운 프로세스는 context switching을 통해 로드해와야함 -> save & reload
-> 이 context들은 PCB에 표시됨.
이때, context switching time은 다 overhead로, 전환할 때 다른 프로세스를 실행하지 않음!
하드웨어 상황에 따라 시간이 달라짐.
프로그램이 메모리에 올라가서 프로세스가 됨.
이때, 프로세스가 항상 새로 만들어지는 것이 아니라 pid=1인 첫 프로세스(Parent)가 부팅 때 만들어짐.
Parent 프로세스가 Child 프로세스를 만들고, 이 프로세스가 또 Child 프로세스를 만들고...를 반복하면서 트리 구조가 형성됨!
-> 구별하기 위해 process identifier라는 pid를 사용함
Process Creation은 대개 비슷하지만, 옵션이 있음
① Resource Share Option
② Execution Options
① 저장소에서 프로그램의 code, data를 그대로 프로세스 memory에 넣는다.
② empty stack을 만들어준다.
③ PCB를 만들고 초기화 해준다.
④ ready queue에 프로세스를 넣는다.
⑤ 다음 프로세스부터는 child의 pid만 다르게, 그대로 clone한다.
fork() 함수를 이용해서 clone하는데, pid만 다르게 clone하기 때문에 부모와 자식이 같은 프로그램을 실행하게 된다. 따라서 exec() 함수를 이용하여 새 프로그램으로 덮어 씌운다.
① 현재 process를 중지하고 state 저장한다.
② 현재 process의 code, data, stack, heap, PCB를 복제해서 새로운 process 생성한다.
-> 이때, 부모와 자식의 차이는 pid와, fork()의 return value이다.
-> fork()의 return value : 자식일 경우 0, 부모일 경우 양수(자식의 pid를 리턴), 에러났을 경우 음수.
-> 또한, 복사 비용을 줄이기 위해 cow(copy on write) 방식을 사용한다. 다 복사하는 것이 아니라 empty stack은 만들되, pointer structure를 만들어 부모의 code, data 영역을 가리키게 했다가 exec()를 통해 새로운 프로그램을 할당 받을 때 진짜 영역을 만들어낸다.
③ 새로운 process를 ready queue에 넣는다.
프로세스를 종료할 때는 exit() 함수를 사용한다. 부모는 자식이 종료될 때까지 wait() 함수를 통해 기다린다.
① 작업을 마친 자식 프로세스가 exit()를 통해 시스템에게 알린다. (system call)
② 자식 프로세스에게 할당되었던 각종 자원들이 다시 반납된다. (하지만 프로세스 상태와 pid가 저장되는 프로세스 테이블의 해당 항목들은 남아있음!)
③ 그러면 부모는 wait() 함수를 호출하여, 종료한 자식 프로세스의 output status data와 pid를 부모에게 return하도록 한다. -> pid = wait(&status);
하지만 다음과 같은 경우 abort() 함수를 사용하면, 부모가 (자식의 eixt() 호출 없이도) 자식 프로세스를 강제로 종료시킬 수 있다.
시스템 안에 있는 프로세스들은 independent일 수도, cooperating일 수도 있음.
이때, cooperating한 프로세스들은 서로 영향을 받음!
왜냐하면, 정보 공유, 컴퓨터 스피드 업, 모듈화, 편리성 등을 위해~
그래서 프로세스끼리 소통을 하기도 하는데, 이것을 Inter-process Communication이라고 부름!
방법 ① Shared memory (책장을 같이 쓴다)
방법 ② Message passing (책장에 편지를 꽂아 논다) : message queue