Process | 프로세스
프로세스 = 실행중인 프로그램
프로세스의 문맥(context)
- CPU 수행 상태를 나타내는 하드웨어 문맥
: Program Counter
: 각종 register
- 프로세스의 주소 공간
: code, data, stack
- 프로세스 관련 커널 자료 구조
: PCB(Process Control Block)
: Kernel stack
프로세스의 상태
Running
, Ready
, Blocked | wait | sleep
Running
: CPU를 잡고 instruction을 수행중인 상태
Ready
: CPU를 기다리는 상태(메모리 등 다른 조건 모두 만족)
Blocked | wait | sleep
: CPU를 주어도 당장 instrunction을 수행할 수 없는 상태
: Process 자신이 요청한 event가 즉시 만족되지 않아 이를 기다리는 상태
: 공유 데이터를 다른 곳에서 쓰고 있어서 내가 처리할 수 없는 상태도 포함됨
프로세스 상태도
PCB
- Process Control Block
- 운영체제가 각 프로세스를 관리하기 위해 프로세스당 유지하는 정보
문맥 교환(Context Switch)
- CPU를 한 프로세스에서 다른 프로세스로 넘겨주는 과정
- CPU를 내어주는 프로세스의 상태를 그 프로세스의 PCB에 저장
- CPU를 새롭게 얻는 프로세스의 상태를 PCB에서 읽어옴
CPU를 얻었다 뺐겼다 반복하기 때문에 어디까지 수행되었고, 다음 수해할 것이 무엇인지 파악하기 위해서 기록해두는 격
System call
이나 Interrupt
발생 시 반드시 context switch가 일어나는 것은 아님
ex) 프로세스 A가 실행되다가 system call
을 해서 kernel로 넘어갔다가 다시 A로 넘어오는 경우 => 문맥 교환이 아님
그렇다고 이 경우에 PCB의 정보가 아예 업데이트되지 않는 것은 아님
프로세스를 스케줄링하기 위한 큐
- Job queue
현재 시스템 내에 있는 모든 프로세스의 집합
- Ready queue
현재 메모리 내에 있으면서 CPU를 잡아서 실행되기를 기다리는 프로세스의 집합
- Device queue
I/O device의 처리를 기다리는 프로세스의 집합
프로세스는 각 큐를 오가며 실행됨
스케줄러 | Scheduler
Long-term scheduler | job 스케줄러
- 시작 프로세스들 중 어떤 것들을 ready queue로 보낼지 결정
- 프로세스에 memory를 주는 문제
- degree of Multiprogramming을 제어
: 메모리에 프로세스를 얼마나 할당할지의 문제
- time sharing system에는 보통 장기 스케줄로가 없음(무조건
ready
)
Short-term scheduler | CPU 스케줄러
- 어떤 프로세스르 ㄹ다음번에 running 시킬지 결정
- 프로세스에 CPU를 주는 문제
- 충분히 빨라야함(timer나 interrupt가 발생할 때마다 처리해야하기 때문에)
time sharing system에서 장기 스케줄러가 보통 없기 때문에 degree of Multiprogramming를 제어할 수 없고 따라서 메모리를 관리할 수 없음. 그래서 두는 것이 아래 중기 스케줄러
Medium-turm scheduler | Swapper
- 여유 공간 마련을 위해 프로세스를 통째로 메모리에서 디스크로 쫓아냄
- 프로세스에게서 memory를 뺏는 문제
- degree of Multiprogramming을 제어
- 기존의 프로세스의 상태는
Running
, Ready
, Blocked
가 있었는데 중기 스케줄러가 등장하면서 Suspended | stopped
가 하나 더 추가됨
- 중기 스케줄러로 인해서 메모리에서 쫓겨난 프로세스 등을 일컫음
Blocked
vs Suspended
Blocked
: 자신이 요청한 event가 만족되면 Ready
Suspended
: 외부에서 resume해 주어야 Active
프로세스의 상태도(추가)
Thread | 스레드
"웹브라우저를 여러개 띄우더라도, 실행 파일이 같으니 똑같은 코드이지 않은가. 좀 더 효율적으로 할 수는 없을까?"
- 같은 프로그램에 대해서 프로세스 하나를 새로 만드는 것이 비효율적이고 각각이 따로 메모리에 올라가는 것도 비효율적임
- 스레드: 프로세스 내부에서 CPU 수행의 단위
스레드의 구성
- program counter
- register set
- stack space
스레드가 동료 스레드와 공유하는 부분(=task)
- code sectoin
- data section
- OS resources
스레드의 장점
- 응답성
다중 스레드로 구성된 테스크 구조에서는 하나의 서버스레드가 blocked
상태인 동안에도 동일한 테스크 내의 다른 스레드가 실행(running
)되어 빠른 처리를 할 수 있다.
- 자원 공유
binary code, data, resource를 공유함
- 경제성
process을 새로 만들고 swiching하는 비용을 아낄 수 있음
- 동일한 일을 수행하는 다중 스레드가 협력하여 높은 처리율(throughput)과 성능 향상을 얻을 수 있다
- 병렬성
Multiprocessor 환경에서 스레드를 사용하면 병렬성을 높일 수 있음
Web browser 예시
하나의 스레드가 네트워크로부터 이미지를 받아오는 동안에
다른 스레드가 나머지 html(text라던지)를 먼저 그려서 사용자 편의성을 높일 수 있음
PCB 도식화
- Process Control Block
Single and Multithreaded Processes
구현
- Kernel Threads
운영체제가 스레드의 존재를 인지
- User Threads
운영체제가 스레드의 존재를 인지하지 못함
프로세스 생성
- 부모 프로세스가 자식 프로세스를 생성
Q. 부모 프로세스가 자식 프로세스를 직접 만들 수 있는가?
A. 프로세스가 직접 하지는 못하고 운영체제에 요청을 해서 만드는데 그 요청이 바로 fork() 시스템 콜
- 프로세스의 트리(계층 구조) 형성
- 프로세스는 자원을 필요로 함
운영체제로부터 받거나 부모와 공유(이례적)
- 자원의 공유
부모와 자식이 모든 자원을 공유하는 모델
일부를 공유하는 모델
전혀 공유하지 않는 모델
- 수행
부모와 자식이 공존하며 수행되는 모델
자식이 종료될때까지 부모가 기다리는(blocked) 모델
- 주소 공간(Address space)
자식은 부모의 공간을 복사함(binary and OS data)
자식은 그 공간에 새로운 프로그램을 올림
Q. 모든 자식 프로세스가 부모 프로세스를 복사한 것에 불과하면 모두 같은 프로세스만 돌리는것인가?
A. 부모의 프로세스를 복사하고 새로운 프로그램을 덮어씌우는 것이 바로 exec()
프로세스 종료(Process Termination)
- 프로세스가 마지막 명령을 수행한 후 운영체제에게 이를 알려줌(exit)
자식이 부모에세 output data를 보냄
프로세스의 각종 자원들이 운영체제에게 반납됨
- 부모 프로세스가 자식의 수행을 종료시킴(abort)
자식이 할당 자원의 한계치를 넘어섬
자식에게 할당된 테스크가 더 이상 필요하지 않음
부모가 종료(exit)하는 경우
운영체제는 부모 프로세스가 종료하는 경우 자식이 더 이상 수행되도록 두지 않는다(*단계적인 종료)
프로세스와 관련한 시스템 콜
fork()
: create a child(copy)
exec()
: overlay new image
wait()
: sleep until child is done
exit()
: frees all the resources, notify parent
fork() 시스템 콜
: 복제 생성
: 자식을 하나 만들어달라고 요청하는 시스템 콜
: 어디까지 실행되었는지까지도 복사가 되며, pid를 통해 부모인지 자식인지 구분
: 부모의 pid
값. 즉,fork()
의 return 값은 자식의 pid값임
Parent process(pid > 0
)
Child process(pid = 0
)
: 위와 같은 구분에 따라 부모와 자식을 다른 프로세스로 분기할 수 있음
exec() 시스템 콜
: 덮어 씌우기
: 현재 프로그램에 새로운 프로그램 덮어씌우기
: 보통 fork()
로 자식 프로그램을 만들고 exec()
를 통해 덮어씌워서 완전히 새로운 프로그램을 생성
: 현재 프로그램을 덮어씌웠기 때문에 다시 원래 코드로 복귀가 불가능함. 즉, exec()
시스템 콜 뒤에 코드는 죽은 코드
wait() 시스템 콜
- 자식이 종료될 때까지 부모를
wait
시킴
- 프로세스 A가 wait() 시스템 콜을 호출하면
⇒ 커널은 child가 종료될 때까지 프로세스 A를 sleep시킨다(block 상태)
⇒ Child precess가 종료되면 커널은 프로세스 A를 깨운다(ready 상태)
exit() 시스템 콜
- 프로세스를 종료 시킴
- 자발적 종료
: 마지막 statement 수행 후 exit() 시스템 콜
: 프로그램에 명시적으로 적어주지 않아도 main 함수가 리턴되는 위치에 컴파일러가 자동 삽입
- 비자발적 종료
: 부모 프로세스가 자식 프로세스를 강제 종료시킴
자식 프로세스가 한계치를 넘어서는 자원을 요청하거나 자식에게 할당된 테스크가 더 이상 필요하지 않을 경우
: 키보드로 kill, break 등을 입력허는 경우
: 부모가 종료하는 경우
부모 프로세스가 종료하기 전에 자식들이 먼저 종료됨
프로세스 간 협력
독립적 프로세스
- Independent process
- 프로세스는 각자의 주소 공간을 가지고 수행되므로 원칙적으로 하나의 프로세스는 다른 프로세스의 수행에 영향을 미치지 못함
협력 프로세스
- Coopertaing prcoess
프로세스 협력 메커니즘을 통해 하나의 프로세스가 다른 프로세스의 수행에 영향을 미칠 수 있음
프로세스 간 협력 메커니즘(IPC)
- IPC: Interprocess Communication
- 메시지를 전달하는 방법
message passing
- 커널을 통해 메시지 전달
- 주소 공간을 공유하는 방법
- 직접 message를 보내는 방법은 없고 운영체제가 매개가 됨
shared memory
- 서로 다른 프로세스 간에도 일부 주소 공간을 공유하게 함
Thread
스레드는 사실상 하나의 프로세스이므로 프로세스 간 협력으로 보기는 어렵지만 동일한 process를 구성하는 스레드들 간에는 주소 공간을 공유하므로 협력이 가능
📚 참고
KOCW | 운영체제 | 이화여자대학교 | 2017-1 | 반효경
Photo by Tianyi Ma on Unsplash