이 글은 KOCW에 공개되어있는 '반효경 교수님'의 운영체제 강의 및 강의 교재 Operation System Concepts(a.k.a 공룡책🦕)의 내용을 기반으로 작성했습니다.
이번 챕터에서는 프로세스에 관해 정리해보겠습니다
오류가 있다면 댓글로 정정 부탁드립니다
프로세스
A program in Execution(실행중인 프로그램)
| 프로세스 문맥(Context)
CPU 수행 상태를 나타내는 하드웨어 문맥
- Program Counter(명령어 포인터) : 레지스터의 일종으로 다음에 실행될 명령어의 주소를 가지고 있어 실행할 기계어 코드의 위치를 지정한다
- 각종 register
process context를 알고있다면 프로그램 실행이 중지됐던 그 다음 시점부터 실행할 수 있다
| 프로세스 상태(Process State)
프로세스 상태는 위와 같이 바뀐다
1) Ready Queue에 대기하고 있던 첫번째 Process가 CPU를 점유하고 Running 상태가 된다
2-1) Time Interrupt를 당하면 Process는 Ready Queue의 맨 뒤로 가서 대기하게 된다(Process Ready 상태)
2-2) I/O 요청이 들어오는 경우 해당 I/O Queue에 대기하게 됨(Blocked 상태)
2-3) 소프트웨어 공유 자원을 요청할 경우 Resource Queue에 대기를 하게 된다
3) I/O 요청이 끝날 경우 메모리 영역에 해당하는 데이터를 넣어주며, Process의 상태를 Blocked에서 Ready로 바꿔주게 된다
- New : 프로세스가 생성 중인 상태
- Running : CPU를 잡고 있는 상태
- Ready : CPU를 잡기 위해 대기하고 있는 Process, Ready 상태인 것들끼리 Time Sharing을 진행
- Blocked(Wait, Sleep) : IO 작업 등을 실행하고 있기 때문에 당장 Instruction을 실행하지 못하는 상태
- Suspended(Stopped) : 외부적인 이유로 프로세스의 수행이 정지된 상태, 프로세스는 디스크로 통째로 Swap out 됨. 중기 스케쥴러에서 사용 됨(뒤에 설명 나옴)
- Terminated : 프로세스가 종료 중인 상태
문맥교환(Context Switch)
CPU가 사용자 프로세스 하나로부터 또 다른 프로세스로 넘어가는 과정
프로세스는 짧은 시간 간격으로 cpu를 얻었다 뺏겼다를 반복하게 된다
이때 CPU를 다시 얻어서 진행할 때 처음부터 실행하는 것이 아니라 실행하던 부분을 기억해서 실행하는 것이 중요하다
CPU를 빼앗길 때 register에 저장돼있던 값을 그 프로세스의 PCB에 저장을 한다
CPU를 다시 얻을 때 Process Context를 PCB에서 찾아 하드웨어에 다시 복원을 한다
| PCB(Process Control Block)
프로세스를 관리하기 위해 운영체제가 OS 커널의 DATA 영역에 두는 정보
① OS 가 관리상 사용하는 정보
- Process State, Process Id
- Scheduling information, Priority(CPU 할당 우선순위 정보)
② CPU 수행 하드웨어 값 :
- Program Counter(Process Context 관련 정보), Registers
③ 메모리 관련
④ 파일 관련(오픈 하고 있는 파일이 어떤 것인지 등 Resource 관련 정보)
- Open File Descriptors ...
- System call이나 interrupt 발생 시 반드시 context switch가 일어나는 것은 아니다(System Call 후 다시 해당 프로세스 실행하는 경우 context switch가 일어났다고 할 수 없음)
- Cache Memory Flush : 문맥 교환이 일어날 경우 Cache Memory가 다 사라져야 한다는 것(Overhead 발생)
프로세스 스케쥴링
| JOB Queue
Job Queue는 프로세스를 스케쥴링 하기 위한 큐
- Job Queue : 현재 시스템 내에 있는 모든 프로세스의 집합
- Ready Queue : 현재 메모리 내에 있으며, CPU를 잡아 실행되기를 기다리는 프로세스의 집합
- Device Queue : I/O device의 처리를 기다리는 프로세스의 집합
- Pointer 을 이용하여 PCB를 큐에 줄 세우게 된다
- 프로세스들은 각 큐를 오가며 수행된다
| Scheduler
1) Long-term schedule(job scheduler/장기 스케쥴러)
- 메모리를 어떤 프로세스에 줄 지를 결정하는 문제
- Process New -> Process Ready 가 될 때 메모리가 admitted 되는데, 이 때 메모리를 줄 지 안줄 지를 결정한다
- degree of multiprogramming : 메모리에 올라가있는 프로세스의 수를 제어하는 것이 long term
- 메모리에 프로그램이 너무 적게/많게 올라가면 성능이 좋지 않기 때문에 메모리에 올라가있는 프로세스의 수를 조절 해야 함
- Time Sharing 방식을 사용할 때는 Process가 무조건 Ready 상태이기 때문에 장기 스케쥴러가 없다
- Time Sharing 방식에서는 장기 스케쥴러 대신 중기 스케쥴러가 메모리 조절을 한다
2) Short-term scheduler(CPU Scheduler/단기 스케쥴러)
- 다음 프로세스에 cpu를 줄 지를 결정하는 것(어떤 Process를 Running 시킬 지 결정)
- milisecond 단위로 스케쥴링이 이루어짐
3) Medium-Term Scheduler(Swapper/중기 스케쥴러)
- 여유 공간 마련을 위해 프로세스를 통째로 메모리에서 디스크로 쫓아냄
- 중기 스케쥴러에서는 Process State에 Suspended(Stopped) 추가 됨
- Suspended(Stopped) : CPU 혹은 외부에서 프로세스를 중지시켜놓은 상태. 메모리에서 쫓겨나서 디스크로 swap out 된다
- 사용자도 process를 중지시킬 수 있으며(break key), 사람이 재개 시켜줘야만 메모리를 사용할 수 있다
- Blocked 와 다르게 외부에서 정지시켰기 때문에 외부에서 resume 해주어야 Active
- 장기 스케쥴러 대신 degree of multiprogramming 제어
스레드(Thread)
Proces 내부의 CPU 수행 단위가 여러개 있는 것
- 동일한 일을 하는 프로세스를 여러 개 만들 경우, 메모리 주소 공간이 여러 개 만들어지므로 낭비이다
- 프로세스는 하나만 생성하고, CPU 수행 단위(스레드)만 여러 개 생성해 각 스레드마다 프로세스의 다른 부분의 코드를 실행할 수 있도록 한다
- 스레드마다 Stack을 따로 나누어 쓰게 되며, 스레드가 함수를 호출하면 함수 호출 정보를 각각의 stack에 쌓게 된다
- 프로그램 카운터(Program Counter) : CPU가 스레드 Code의 어느 부분을 실행하고 있는 지를 가리키는 register
- PCB에 각각의 프로그램 카운터 정보를 별도로 저장한다
| 스레드의 장점
- 응답성 : 하나의 서버 스레드가 blocked 돼도, 동시에 다른 스레드는 running 상태일 수 있어 응답시간이 빠르다
- 자원 공유 : 프로세스의 자원들을 공유하며 메모리 낭비를 줄일 수 있다
- 경제성 : 스레드를 만드는 것이 프로세스를 만드는 것 보다 오버헤드가 적다(스레드 == 가벼운 프로세스). 또한 스레드 간 CPU Switching은 프로세스 간 Context Switching보다 오버헤드가 적다
- CPU가 여러 개인 아키텍쳐의 경우 스레드를 이용해 병렬성을 높일 수 있으며, 다중 스레드의 협력으로 성능 향상 가능
| 스레드 구현
1) 커널스레드
- 스레드가 여러개 있다는 사실을 운영체제 커널이 알고 있음
- 하나의 스레드에서 다른 스레드로 cpu가 넘어가는 것도 cpu scheduling 하듯 넘겨주게 된다
2) 유저스레드
- 라이브러리를 통해 지원
- 프로세서 안에 스레드가 여러개가 있다는 것을 운영체제는 모르고 유저 프로그램이 라이브러리의 지원을 받아 관리한다
- 구현상 제약점 등이 있을 수 있다