운영체제3 Processes
안녕하세요. 옆집 컴공생입니다. 오랜만에 운영체제 복습을 하네요. 그럼 시작해보겠습니다.
이번 챕터 3는 Processes 에 대해 배워보겠습니다.
목표
- Process 의 개념
- Process Scheduling
- Process 의 동작
- Process 간의 통신
- IPC( Process 간의 통신) 의 예
- Client-Server Systems 과 IPC 와의 차이점
▶프로세스란 ?
- 실행되고 있는 프로그램
- scheduling , 생성(creation) , 종료(termination), 통신(communication) 과 같은 이슈들이 생기게 됩니다.
- process 들 간에 통신은 공유 메모리(shared memory) 와 메세지 패싱(massage passing)을 통해 이루어집니다.
Process 의 개념
- 과거의 컴퓨터는 단 하나의 프로그램(job)만 실행할 수 있었습니다. 이를 Batch system 이라고 했습니다.
- 시분할 시스템(Time-shared systems)은 하나만 실행되고(tasks) 있는데 여러개가 실행되고 있다고 생각하게 만들었습니다.
프로세스는 여러 파트로 이루어져 있습니다.
- text section : program code
- program counter : 다음에 실행될 Instruction 의 위치를 가리킵니다.
- Stack : 함수 파라미터, 리턴 주소, 지역 변수 등이 들어가 있습니다. 임시 데이터입니다.
- Data section : global variables
- Heap : 동적 데이터
Passive 한 프로그램과 달린 Process 는 active 합니다. 실행가능한 프로그램이 메모리에 로딩이 되면 그게 프로세스가 됩니다. 하나의 프로그램은 여러개의 Process 로 실행이 됩니다.
Process 의 State
프로세스는 state를 바꾸면서 실행이 됩니다. 상태는 다음과 같습니다.
1. new : 프로세스 생성
2. ready : processor 에 할당되기를 기다리는 준비 단계
3. running : Instructions 이 실행되고 있는 단계 (Scheduler가 dispatch 해줌)
4. waiting : running되다가 입출력 이벤트를 기다리게 되는 상태, 이벤트가 완료되면 ready 상태로 감
5. terminated : process 가 종료
Process Control Block(PCB)
PCB에는 각 프로세스에 대한 정보가 들어 있습니다.
▷ Process state - running 인지 waiting 인지 등등
▷ Program counter - 다음 번 실행될 명령어의 위치
▷ CPU registers, CPU scheduling information, Memory-management information, 등등... 을 가지고 있습니다.
CPU Switch From Process to Process
다음은 Context switching 에 관한 그림입니다.
두개의 프로세스가 등장합니다. 프로세스 P0가 계속 진행되고 있다가 프로세스 P1 에 의해 interrupt가 걸린 상황입니다. 그럼 P0는 CPU 에서 진행이 되다가 P1에게 자리를 넘겨 주어야하기 때문에 다시 실행되기 전까지의 정보를 PCB(Process Control Block)에 저장하게 됩니다. 그리고 PCB에 저장되어 있던 P1가 Reload 됩니다.
그리고 P0이 다시 P1에게 Interrupt 가 되어 저장하고 다시 P0가 Reload 되는 상태입니다.
Threads
Process는 실행되는 플로우 흐름이 하나이고 Threads는 여러개입니다.
Multiple program counters per process 입니다. Instructions 을 가리키는 프로그램 카운터가 여러개라는 의미는 프로세스의 코드 자체가 여러개가 실행될 수 있다는 의미입니다.
Process Scheduling
이를 하는 이유는 CPU의 사용률을 높이기 위해서 입니다. 입출력이 느리기 때문입니다.
스케줄링을 위한 큐가 존재합니다.
- Job queue : 하드디스크같은 곳에 있고 이 안에는 시스템 상에 모든 프로세스가 존재합니다.
- Ready queue : 메모리상에 존재하고 할당되고 실행되기 기다리는 프로세스가 있습니다.
- Device queue : 입출력 디바이스와 관련된 동작을 기다리는 프로세스가 있습니다.
아래의 그림은 Ready queue 와 I/O Device Queue 의 그림입니다.
Ready queue를 보면 다음 프로세스를 가리키는 Head와 마지막을 가리키는 Tail 을 볼 수 있습니다.
다음은 CPU에서 실행되다가 여러가지 이유로 Ready queue 로 돌아가게 되는 상황입니다.
1. I/O request : 해당 프로세스에 대한 입출력의 동작 발생, 느리기 때문에 그 사이에 다른 프로세스가 dispatch 됨.
2. Time Slice Expired : 기본적으로 CPU는 time shared 이기 때문에 만약 해당 슬롯에 10초가 정해 졌으면 이 시간이 지난 후에는 ready queue로 들어가게 됩니다.
3. Fork a child : child 를 fork 하면 Parent 가 되기 때문에 child process 가 실행이 끝날 때까지 기다려야합니다.
4. Wait for an interrupt : interrupt 에 의해 CPU 에서 강제로 제거되고 Ready queue 에서 대기하게 됩니다.
프로세스가 정상 종료가 될때까지 이 주기가 반복됩니다.
▶Short-term scheduler (or CPU scheduler)
: Ready Queue 에 있는것을 CPU에 할당(= 실행)
빠른 CPU 에 할당을 하는 거기 때문에 빨리 빨리 Switching 이 됩니다. (milliseconds)
▶Long-term scheduler(or job scheduler)
: Job queue에 있는 프로세스를 메인 메모리에 있는 Ready Queue로 가져옴
상대적으로 느리게 동작(seconds, minutes)
▶Medium-term scheduler
: 메모리의 프로세스를 제거하고 하드디스크의 저장, 그리고 실행을 계속하기 위해 디스크로 부터 가져옴. => Swapping
Swap in : 하드 디스트 프로세스 -> main memory Ready queue
Swap out : CPU 에서 실행되고 있는 프로세스 -> 하드디스크
각각의 스케줄러가 어디서 어디로 프로세스를 옮기는지 잘 알아야합니다.
모바일 시스템 상에서의 멀티태스킹(Multitasking)에 대해 배워보겠습니다.
현대의 OS에서는 여러 프로그램을 동시에 실행시켜줄 수 있게 해줍니다. 그럼 모바일 OS는 어떨까요?
당연히 멀티태스킹을 지원해주지만 기존의 방식과는 조금 다른 형식을 사용합니다. 모바일 OS에서는 UI 화면 권한을 가지는 프로세스의 비중을 더 많이 두고 있습니다.
Context Switch
멀티태스킹 이야기를 하면 콘텐트 스위칭은 빠질 수가 없는 주제입니다.
Context Switch 이란 CPU가 지금 실행하는 프로세스가 아닌 다른 프로세스를 사용하고자 하는겁니다.
당연히 기존에 프로세스를 저장하고(Save) 새로운 프로세스를 사용해야합니다.(Load)
이때 프로세스의 정보들은 PCB안에 들어있습니다. 당연히 이 PCB가 클수록 Context Switch 에 시간은 오래 걸리게 됩니다. Context Switch 자체가 원래 시간이 오래 걸리는 작업이기도 합니다 . (Context-switch time is overhead)
Process 의 동작
1. Process Creation
부모 프로세스가 자식 프로세스를 생성하는 과정을 살펴보겠습니다.
프로세스는 기본적으로 식별자, 즉 id 를 가지고 있습니다. 이를 pid라고 합니다.(Process identifier) 이 pid 를 통해서 프로세스 간에 관계를 파악할 수 있습니다.
부모 프로세스와 자식 프로세스 간엔 리소스를 공유하거나 일부만 공유하거나 공유를 하지 않는 등 다양한 옵션이 존재합니다. 또한 실행 될때도 부모와 자식 프로세스가 동시에 실행이 되거나 자식 프로세스가 끝날때 까지 부모 프로세스가 기다리는 경우도 있습니다.
UNIX
▶fork()을 통해 새로운 프로세스를 만들어냅니다. 이때 부모 프로세스의 pid > 0 이고 자식 pid =0 입니다.
▶exec() , fork() 이후에 실행되는데 특정 새로운 프로그램이 실행이 됩니다. 컨텐츠를 로딩하고 실행하는 겁니다.
2.Process Termination
- 자식 프로세스가 정상적으로 동작을 끝내고 자발적으로 exit() system call 을 호출하는 경우가 있습니다. 이 때는 부모 노드의 wait() 함수가 끝나고 상태정보를 받고 OS로 하여금 리소스가 해제됩니다.
- 부모 프로세스가 자식 프로세스를 Abort() 함수를 이용해 강제적으로 종료시킵니다. 자식 프로세스가 리소스를 초과해서 받을때, 자식 프로세스가 더이상 필요하지 않을때, 부모노드가 왠지 모르게 죽었을때 운영체제가 나서서 자식 프로세스를 죽입니다.
-cascading termination : 단계적으로 프로세스가 죽는 고정
▶좀비 프로세스
- 자식 프로세스가 끝났는데 부모 프로세스가 없는 경우입니다. 그렇기 때문에 자원을 해제해 준다던지 하는 프로세스 종료 후속 작업을 실행하지 못했기 때문에 좀비 프로세스가 되는 겁니다.
▶orphan 프로세스
- 부모프로세스가 wait() 없이 갑자기 죽어버립니다. 좀비 프로세스가 같지 않냐구요? 이 경우에서는 init process가 parent 를 대신하여 child process의 후속 작업을 실행하게 됩니다.
Interprocess Communication
- 프로세스 간 협력 이유
정보 공유, 속도 향상, 편의성
-> 협력을 하기 위해서 통신이 필요합니다. 이런 걸 interprocess comunication(IPC)라고 합니다 .
1) Shared memory 2) Message passing(공유된 메모리가 없음)
이렇게 프로세스들 간에 협력에서 발생하는 이슈가
Producer-Consumer Problem
입니다.
정보를 공유하게 되면 producer 프로세스와 consumer 프로세스가 있게 됩니다. 이 때 이 둘 사이에 사용할 수 있는 메세지의 크기가 한정되어 있으면 bounded buffer 이고 무한정이면 unbounded buffer 입니다.
▶아래 동작을 가정해봅시다.
Producer 는 자신의 작업후 결과를 Consumer 에게 부여하고 싶습니다.
Consumber 는 Producer 로부터 수신된 데이터를 처리하고 싶습니다.
그럼 다음 그림과 같은 상황이 발생합니다.
1. Producer 가 작업을 끝내고 Consumer 에게 보냅니다. 근데 Consumer 가 받을 수 없는 상황에 있었습니다.
2. 그래서 보내지 못하고 waiting 하게 됩니다.
3. Consumer 에게 보낼 수 있는 상황이 와서 데이터를 보냅니다. 그 데이터에 맞는 처리를 시작합니다.
4. 그리고 Producer는 여기서 2단위 작업을 진행합니다 .이때까지 Consumer 는 할 게 없어서 idle 상태가 됩니다.
5.Produce가 데이터를 보내고 Comsumber 가 이 단위 작업을 진행하는 데 Producer는 한 단위 작업을 끝내고 보낼 수 가 없음으로 Idle 한 상태 입니다.
이와 같이 프로세스가 계속 일하고 있는게 아니라 노는 시간이 생기는 문제를 Producer - Consumber Problem 이라고 합니다 .
그럼 어떻게 idle 한 상황을 줄일 수 있냐? 다음 그림과 같은 방법이 있습니다.
▶버퍼를 도입해 Producer가 작업이 끝나면 buffer 에 저장해줍니다. 그리고 다른 작업을 할 수 있습니다.
이때는 Producer 와 Consumber 에 직접적인 통신이 없기 때문에 정상동작이 힘들 수도 있습니다.
▶다음은 공유된 메모리를 사용해보겠습니다.
이렇게 되면 buffer 하나를 사용하지 못하는 점에서 비효율적인 면을 보입니다.
Message Passing
에 대해 알아 보겠습니다.
두 가지 동작이 있을 수 있습니다.
send(message) 와 receive(message) 가 있습니다 .
message passing 에서는 P와 Q에 공유된 메모리 공간이 없습니다.
통신을 할때는 communication link를 통해서 메세지를 직접 주고 받습니다.
▶send(P, message) - 누구에게 보내느냐
▶receive(Q, message) - 누구로부터 받느냐
Indirect Communication
직접 교환을 하는게 아닌 방식으로 Mailboxes(ports) 가 있습니다.
이 Mailboxes로 메세지를 보내고 여기로 부터 받습니다. 각각의 메일 박스는 유니크한 id를 갖습니다.
동작
1. 메일박스 생성
2. 메일박스 송수신
3. 메일박스 없앰
▶send(메일박스, 메세지)
▶receive(메일박스, 메세지)
그리고 1대 다 통신이 가능합니다. 대신 동시에 접근은 되지 않고 순차적으로 접근이 가능합니다. 접근 순서는 OS 에 스케쥴링이 해줍니다.
Synchronization
▶Blocking - synchronous
Blocking send 는 receive() 함수에 의해서 수신이 확인되기 전까지 다음 sender 를 진행하지 않습니다.
Blocking receive 는 메세지가 올때까지는 Block 됩니다.이는
send 가 아무 일도 안 하고 메세지 오기를 기다리기 때문에 비효율적이라고 볼 수 있습니다.
▶Non-Blocking - asynchronous
Non-Blocking send 는 계속 메세지를 보낼 수 있습니다. 그리고 이 메세지는 queue 에 보내집니다. 그리고 이 큐는 무한의 크기가 있어야합니다. (unbounded msg buffer)
Non-Blocking receive 는 수신쪽에는 계속 읽고 없으면 없구나 라는 신호를 얻는겁니다.
효율적이지만 복잡한 매커니즘이 필요합니다.
보면 보낼 건 보내고 다시 자기 일을 하는 걸 볼 수 있습니다.
만약 send , receive 가 Blocking 이라면 buffer 가 필요가 없습니다. 이를 rendezvous(랑데뷰)라고 합니다.
Buffering
버퍼링은 메세지가 들어있는 Queue에 개념입니다.
1. Zero capacity 는 블락킹이 된 send와 receive 일 때 입니다. 이때는 버퍼가 필요하지 않습니다.
2. Bounded capacity 는 한정된 공간의 큐입니다.
3. Unbounded capacity 는 무한한 공간의 큐입니다.
▷Examples of IPC Systems - POSIX
1. 공유 메모리 생성
2. 공유 메모리의 크기를 조정
3. 메모리를 포인터공간으로 Mapping 시킴
4 공유 메모리에 Write
이렇게 하면 "Writing to shared memory" 라는 내용이 shared_memory 에 저장이 됩니다.
Consumer 입장
Consumer는 공유 메모리를 생성할 필요가 없기 때문에 공유메모리를 가져다가 사용합니다.
1. 공유 메모리 가져오기
2. 자신의 주소 공간으로 맵핑시키기
3. 공유 메모리의 내용 Read
4. 공유 메모리 삭제
▷Examples of IPC Systems - Mach
msg_send(), msg_receive() 기본적인 message passing 을 위한 함수
msg_rpc() 주소 공간이 다른 두개의 프로세스 간의 통신을 위해 있는 함수
(메일박스와 공유메모리는 완전 다른 의미입니다. 공유메모리는 두 프로세스가 동일한 버퍼가 있는거고 메일박스는 시스템에서 제공하는 어떤 제 3의 통신 미디어가 됩니다.)
▷Examples of IPC Systems - Windows
advanced local procedure call(LPC) 을 만들고 있습니다. (공유 메모리와 비슷한 기법)
Connection port 와 Communication port 제공
Server 가 Connection port 를 만들어서 공표합니다. 클라이언트가 포트를 잡아서 통신합니다.
Local Prodedure Calls
클라이언트와 서버가 동일한 주소를 갖음
Remote Prodedure Calls
클라이언트와 서버가 다른 주소를 갖음. 메세지 패싱 기반으로 주소 공간이 맵핑되는 매커니즘이 필요
Communications in Client-Server Systems
-Sockets
-Remote Procedure Calls
-Pipes
▷Socket
- 두 개의 네트워크 상에서 두 프로그램의 실행이될 때 통신을 위한 추상적인 하이 레벨의 End point 입니다.
- IP address 와 port
Remote Procedure Calls
- 중요한 개념
- procedure calls(특정 프로세스를 콜) 을 추상화 -> 떨어져 있는 네트워크 시스템 사이에 프로세스를 동작
복잡해보이지만 결국은 클라이어트에서 서버코드를 Call하는 겁니다.
보면 먼저 Client stub 에서 얻고자 하는 것을 marshalled (마숼링) 해서 서버에 보내면 Server stub 에서 이를 다시 Unpack 합니다. 그리고 그 결과를 Return 하고 이를 다시 marshalled 해서 Client 에 다시 보냅니다. 그럼 Client 에서는 이를 다시 Unpack 해서 가져옵니다 . 이를 지원해주는게 RPC입니다.
Client Stubs - 서버의 위치를 찾고 marshalled
Server Stubs - 메세지를 받고 Unpack
▷Pipes
Orinary pipes부모-자식 프로세스 관계에서만 pipe 통신 가능
Named Pipes - 부모자식 관계가 아니어도 통신 가능, 양방향성
이렇게 챕터 3이 끝났습니다. 수고하셨습니다.