3장에서는 프로세스가 생성될 때의 과정에 대해서 다뤘습니다. 오늘은 그러한 프로세스가 종료되기 위해서 거치는 과정들에 대해 알아봅시다.
Process Termination
우선, 언제 프로세스가 terminated 상태가 되는지 알아보자.
- 프로세스가 exit()라는 시스템 콜을 부를 때
- 프로세스가 다룰 수 없는 signal을 받았을 때
- 자식 프로세스가 더 이상 필요 없어서, 부모가 자식을 kill할 때
signal이란 프로세스끼리 이벤트가 발생했음을 알리는 수단을 의미합니다.
exit() 시스템콜을 사용하여 프로세스를 종료하고 싶다면 아래의 순서로 진행됩니다.
1. OS에 의해서 종료될 프로세스의 자원이 회수됩니다. 여기서 PCB는 제외합니다.
2. 부모 프로세스에게 death-of-child 시그널을 보냅니다.
3. 종료될 프로세스의 상태를 terminate로 설정합니다.
4. 부모 프로세스가 wait()를 호출하면, 자식 프로세스의 PCB에서 accounting information을 읽어가고, 자식 프로세스의 모든 자원은 회수 당합니다.
그렇다면 만약 종료된 프로세스의 자식 프로세스가 존재한다면 어떻게 될까요?? 아래의 상황을 확인해봅시다.
여기서 분홍색으로 표시된 PCB가 종료됩니다. 그렇다면 그 아래에 있는 프로세스들은 어떻게 될까요?? 결과는 아래와 같습니다.
바로, 그러한 자식 프로세스들은 init 프로세스의 자식이 됩니다. init 프로세스에 대해서 간단하게만 설명하면 우리가 최초로 생성되는 프로세스인 swapper가 가장 처음 생성하는 프로세스가 init 프로세스입니다.
이러한 init 프로세스가 기타 여러가지 프로세스를 fork, exec하게 되는 것이죠.
Inter-Process Communication(IPC)
IPC는 프로세스들이 서로 정보를 주고받으면서 소통하는 방식을 일컫습니다.
프로세스들은 서로 정보를 주고받은 것이 필요할 때가 있습니다. 이럴 때 프로세스들은 서로 어떻게 통신할까요?? 단순히 A라는 프로세스가 B에 접근하면 되는 것일까요?? 사실 이런 단순한 방식은 굉장히 위험합니다.
가령, 어떤 해킹 프로세스가 존재하는데, 그 프로세스가 다른 프로세스들을 마구 접근하려고 한다는 것처럼 말이죠.
그래서 OS에서는 어떤 프로세스가 다른 프로세스게 접근하려고 하면 강제로 해당 프로세스를 kill하는 등의 작업을 통해서 우리 컴퓨터를 보호해줍니다.
그렇지만서도, 프로세스들끼리 통신해야하는 경우가 존재합니다. 예를 들면 우리가 키보드로 입력을 하면, 우리의 입력을 받는 프로세스가 존재합니다. 근데 화면에도 출력해야하니까 출력을 보여주는 프로세스도 존재해야겠죠?? 이 두 프로세스간의 관계는 확실히 연관이 있고, 서로 정보 교환이 필요합니다. 따라서, 앞서 말씀드린 통신방법이 아닌 프로세스간에 조금 더 안전하고 효율적인 방법으로 통신하는 방법을 고안해냈습니다.
이번에는 IPC의 두 가지 방식에 대해 알아봅시다.
Message Passing
Message Passing은 프로세스 내에 존재하는 메세지 큐에 자신이 보내고자하는 메세지를 넣은 후에, 커널로 보냅니다. 그리고 커널 내에 있는 메세지 큐에 이걸 넣어놓습니다. 만약 이 메세지를 받고싶어하는 프로세스가 있다면, 해당 프로세스가 커널 모드를 통해 커널에 접근하여 메세지 큐에 있는 내용을 가져올 수 있습니다.
이 방식이 바로 message passing입니다. 위 설명에서도 어느정도 감을 잡으셨겠지만, 이렇게 되면 mode change가 빈번히 일어나게 됩니다. 적어도, 두 번 이상은 발생하게 되고, 이러한 모드 체인지는 시간을 어느정도 소모하므로, 시간적인 측면에서 비효율적이라는 단점이 있습니다.
Shared Memory
말 그대로 공유 메모리. 프로세스 두 개가 서로 통신하고 싶다면, 통신할 수 있는 메모리 주소를 할당받아서 해당 부분에 파일을 쓰고 읽을 수 있게 됩니다. 이렇게 되면 mode change도 없으니 더욱 빠르게 되겠죠.
하지만 아래와 같은 경우들이 문제점으로 떠오릅니다.
만약 A 프로세스가 shared memory에 어떤 데이터를 작성 중에 time slice가 끝났다고 가정해봅시다. 그러면 A는 자신이 지금 작업 중인 부분을 중단하게 됩니다. 그러고 dispatcher가 프로세스 B를 배정해줬다고 합시다.
A와 B는 shared memory를 공유하고 있고, 이제 B는 A가 작성한 정보를 읽어와야합니다. 그런데 메모리 내에 보니까, 값이 쓰여져있습니다. 비록 아직 다 완성된 건 아니지만 말이죠! 그래서 B는 다 완성되지 않은 데이터를 완성되었다고 착각하고 읽어갈 수 있습니다.
따라서, shared memory 방식은 신중한 코드 작성이 필요합니다. 이러한 트레이드 오프 관계에 있지만, shared memory를 많이 사용한다고 합니다.
그림에는 무조건, A와 B 사이에 존재하는 것처럼 표시되어 있지만 그렇지 않습니다. shared memory는 어디에나 가능합니다.
지금까지 프로세스가 종료될 때, 그리고 IPC에 대해서 알아보았습니다.
다음 시간에는 쓰레드에 대해서 알아보겠습니다. 감사합니다.
'CS > OS' 카테고리의 다른 글
[운영체제] 4-3. 멀티쓰레드 (0) | 2023.10.02 |
---|---|
[운영체제] 4-2. 쓰레드 정의 (0) | 2023.09.27 |
[운영체제] 3-3. 프로세스 스위치 (0) | 2023.09.23 |
[운영체제] 3-2. 프로세스 생성 (0) | 2023.09.23 |
[운영체제] 3-1. 프로세스 컨텍스트 (0) | 2023.09.23 |