프로세스
실행 중인 프로그램을 의미한다.
os의 작업의 단위이다.
- 하나의 프로세스가 실행되려면 자원들이 필요하다.
👉 CPU, memory, files, I/O devices
⚡ HDD나 하드 디스크의 storage에 저장되어 있는 프로그램을 메모리에 로드 하면(가령 프로그램 더블클릭) 메모리에 있는 instructions를 fetch해 와서 CPU가 execute 하는 것이 컴퓨터의 구조(폰 노이먼 아키텍쳐)
👉 이 때 execution 상태에 있는 프로그램을 'process'라 한다.(Program in execution)
프로세스의 메모리 레이아웃
메모리에 load된 프로세스를 os가 관리한다.
- Text section: 명령어들이 있음
- Data section: 전역 변수들이 있음
- Heap section: 메모리 할당을 했을 때(java에서는 new, 변수 할당) 힙 영역에 메모리를 확보함(부족해지면 다른 메모리 영역을 할당 받음)
- Stack section: 함수 파라미터, 리턴되는 주소, 지역 변수 등이 저장됨
👉 함수 호출시 호출된 함수가 쌓임
프로세스의 생명주기
- New: 프로세스가 생성된 상태
- Running: 프로세스의 명령어를 cpu에 로드해서 실행한 상태
👉 너무 오래 사용한 경우 os가 interrupt를 주어 waiting 상태로 만듦
👉 Running 중 I/O가 생길 경우 waiting 상태로 가게 됨
- Waiting: 다른 프로세스가 동일한 cpu를 점령해 쓰기 시작할 때 남은 프로세스는 waiting 상태가 된다.
👉 I/O를 했을 경우 이것이 끝날 때까지 대기하는 상태
- Ready: I/O가 끝났다고 시그널이 오면 CPU를 바로 점령하는 것이 아니라 점유할 상태가 다 되어 대기하는 상태가 된다.
👉 Ready Queue에 들어가게 된다.
👉 Ready에서 Running 상태로 만드는 것을 'scheduler가 dispatch'한다고 말한다.
- Terminated: 프로세스가 끝난 상태
PCB(Process Control Block) or TCB(Task Control Block)
- PCB와 TCB는 프로세스를 관리하는 구조체이다.
- PCB 또는 TCB(리눅스 용어)에 process가 가진 모든 정보를 저장한다.
PCB가 가지고 있는 정보
- Process state(new/run/wait/ready/terminate)
- Program counter: 프로그램 실행을 위해서는 메모리에 있는 명령어를 fetch해야 하는데, 이 메모리는 program counter 레지스터에 있는 해당하는 메모리이며(주소처럼) 이를 fetch해 오게 된다. program counter도 일종의 CPU register이다.
👉 다음 번에 실행할 명령어 주소를 기억하는 레지스터
- CPU registers: Instruction Resgier(IR), Data Register(DR).
- CPU-scheduling information
- Memory-management information
- I/O status information
Process란?
- 프로세스는 single thread of execution을 수행하는 프로그램이다.
👉 하나의 실타래와 같다.
- Single thread of control은 한 번에 한 작업만 수행할 수 있다.
- 여러 개를 동시에 수행하는 것을 'multiprocessing', 'multitasking'이라 한다.
👉 os의 가장 핵심적인 기능이다.
- 프로그램이 복잡해지면서 하나의 프로세스 안에서도 'single thread of execution'으로는 부족하여 여러 개의 스레드가 동시에 실행될 필요가 생겼다.
👉 이를 '스레드'라 한며 프로세스보다 더 가볍다.(사실 멀티 프로세싱보다 멀티스레드가 대세이며 장점이 훨씬 더 많다.)
프로세스 스케쥴링
- 멀티프로그래밍의 목적은 여러 개의 프로그램을 동시에 실행하는 것이다. (simultaneously, concurrently)
👉 이를 통해 CPU 사용 효율을 높일 수 있다.(컴퓨터의 CPU는 굉장히 널널하며 놀고 있는 부분이 많다.)
- CPU core 간에 프로세스를 자주 변경하여 사용자 입장에서 각 프로그램이 동시에 도는 것처럼 보이도록 하기 위해 time sharing을 한다.
Scheduling Queue
- CPU를 scheduling 하는 Queue를 말한다.
- ready queue에 있다가 running 상태로 가서 CPU를 점유하게 되고 만약 I/O가 있으면 waiting 상태로 바뀐 뒤 device에서 대기 queue로 가서 I/O completion을 기다린다. 이것이 끝나면 ready 상태로 가게 된다.
👉 ready queue의 실제 구현은 linked list로 한다.
Context Switch
- context란 process가 사용되고 있는 상태를 말한다.
- 이 상태는 모두 PCB에 저장되어 있다. 따라서, PCB 정보를 'context'라 한다.
- 어떤 interrupt가 일어나면 running process에 대한 context(PCB)를 저장한다.
👉 이 때 어디까지 실행했는 지에 대한 정보가 program counter에 저장된다.
👉 CPU를 다시 획득하게 되면 저장해 놓은 context를 restore 하게 된다.
- context switch는 어떤 task가 CPU core를 다른 프로세스에게 넘겨 주는 것이다.
👉 현재 프로세스의 state(PCB)를 저장하고 새로이 CPU를 획득한 process의 PCB를 복원하면 된다.
프로세스로부터 새로운 프로세스 생성하기
프로세스의 tree관계가 생성된다.
- 프로세스를 생성하는 프로세스: parent process
- 만들어진 프로세스: child process
👉 fork()를 이용해서 만든다.
👉 fork()시 child process의 리턴 code는 0인 반면, 1이면 child process의 parent process이다.
p0의 pid = 1004, p0를 fork()하여 만들어진 p1(p0의 child)의 pid = 1005일 때 p0를 fork()한 child process의 pid를 리턴하면 1005가 리턴된다. 그 다음, 이것이 exit()하여 끝나고 나면 p1에서 fork()를 하고 이 때의 pid를 출력하면 pid=0이 된다.(child process)
새로운 프로세스 생성시 execution 상황 2가지
- child와 concurrent 하게 프로세싱하게 될 수 있다.
- parent가 wait하는 상태가 될 수 있다.
새로운 프로세스 생성시 address-space 상황 2가지
- 만약 child와 praent가 똑같은 일을 하는 process라면 실행하는 text가 똑같게 되므로 PCB만 달라지면 되며 process 자체가 달라질 필요는 없다.
👉 메모리에 있는 '주소 공간'을 parent process의 것과 같이 복제한다.
- child process의 새로운 프로그램을 로딩한다.
프로세스 종료시
- system call인 'exit'을 할 수 있다.
👉 OS에 delete 요청을 하는 것이다.
- OS가 메모리 해제하고 모든 리소스를 해제한다.
⚡ Zombie and Orphan
- zombie: parent가 terminate 되지는 않았지만 wait()를 호출하지 않는 경우
👉 부모는 부모일만 함
👉 daemon process, background process 등을 만들 때 주로 활용한다.
- orphan: parent process가 wait를 호출하지 않고 종료하면 child process는 orphan이 된다.
fork() system call
- fork()를 하면 parent process의 address-space를 그대로 복제하며 parent process는 자신의 할 일을 계속한다.
- parent process가 child가 run 하는 동안 child를 기다릴 수 있는데 wait() system call을 이용하게 된다.
👉 그러면 ready queue에서 나와 wait queue로 가게 되고 child process의 interrupt를 기다리게 된다.