프로세스 관리

Tasker_Jang·2026년 9월 23일
post-thumbnail

1. 프로세스는 프로세스가 만듭니다

운영체제가 프로세스를 하나씩 직접 만들어 주지 않습니다. 부모 프로세스(parent process)가 복제해서 자식 프로세스(child process)를 만듭니다. 자식이 또 자식을 만들 수 있으므로 시스템의 프로세스들은 자연스럽게 트리 계층 구조를 이룹니다.

자식이 실행되려면 자원이 필요합니다. 자원을 얻는 경로는 둘입니다. 운영체제에 직접 요청해서 받거나, 부모가 가진 것을 나눠 쓰는 것입니다.

2. 부모와 자식이 지내는 방식

자원과 수행 순서에서 각각 선택지가 있습니다.

구분선택지설명
자원 공유전부 공유 / 일부만 공유 / 공유하지 않음일반적으로는 공유하지 않고, 자원을 두고 경쟁하는 관계가 됨
수행 방식공존하며 수행 / 자식이 끝날 때까지 부모가 기다림뒤쪽이 wait()을 쓰는 경우

주소 공간은 별도입니다. 자식은 부모의 주소 공간을 그대로 복사해서 시작합니다. 같은 code, 같은 data로 시작하지만 그때부터는 남남입니다. 한쪽이 변수를 고쳐도 다른 쪽에는 보이지 않습니다.

3. fork()와 exec()

여기서 쓰이는 것이 시스템콜입니다.

fork()는 자기 자신을 복제합니다. 주소 공간과 PCB가 복사되므로 program counter도 복사됩니다. 그래서 자식은 프로그램 처음이 아니라 fork 다음 줄부터 시작합니다. 부모와 자식을 구분하는 방법은 반환값입니다.

pid = fork();
if (pid == 0) {
    // 자식: fork()가 0을 반환
    exec("/bin/date", ...);   // 여기서 프로그램이 통째로 바뀐다
} else if (pid > 0) {
    // 부모: 자식의 pid를 반환받음
    wait(NULL);               // 자식이 끝날 때까지 기다린다
}

exec()는 복제가 아니라 덮어쓰기입니다. 현재 프로세스의 주소 공간을 새 프로그램으로 바꿔 버리고 그 프로그램의 처음부터 실행합니다. 성공하면 돌아올 자리가 없으므로 exec() 다음 줄은 영원히 실행되지 않습니다.

즉 새 프로그램을 띄우는 일은 "복제하고, 그중 자식을 원하는 프로그램으로 바꾼다"는 두 단계로 이뤄집니다.

4. COW (copy-on-write)

그런데 이 흐름에는 낭비가 있습니다. fork()로 주소 공간을 통째로 복사한 직후에 exec()로 전부 덮어써 버리면, 복사한 내용이 한 번도 쓰이지 않습니다.

그래서 copy-on-write를 씁니다. fork 시점에는 복사하지 않고 부모의 주소 공간을 같이 쓰게 해두었다가, 어느 한쪽이 내용을 바꾸려 할 때 그 부분만 복사합니다.

작은 예제

부모의 주소 공간이 code 20MB, data 80MB라고 하고, 페이지 크기는 4KB입니다.

  1. 단순 복사 방식: fork 시점에 100MB를 복사합니다.
  2. COW 방식: fork 시점 복사량은 0입니다. 부모와 자식이 같은 물리 메모리를 가리킵니다.
  3. 자식이 data의 변수 하나를 고칩니다. 그 변수가 속한 페이지 4KB만 복사됩니다. 지금까지 총 복사량 4KB입니다.
  4. 자식이 곧바로 exec()을 호출하면 주소 공간이 새 프로그램으로 교체되므로, 복사했던 것마저 필요 없어집니다.

읽기만 하는 code 영역은 끝까지 복사되지 않습니다.

5. wait()과 exit()

프로세스를 끝내는 쪽도 시스템콜입니다.

시스템콜하는 일상태 변화
fork()자식 생성자식이 New를 거쳐 Ready로
exec()주소 공간을 새 프로그램으로 교체상태는 그대로 Running
wait()자식이 끝날 때까지 기다림호출한 부모가 Blocked, 자식 종료 시 Ready
exit()자발적 종료호출한 프로세스가 Terminated

exit()은 자발적 종료입니다. 프로그래머가 직접 부르지 않아도 마지막 문장을 지나면 컴파일러가 넣어둔 exit()이 호출됩니다.

반대로 비자발적 종료는 부모가 자식을 강제로 끝내는 경우이며(abort()), 조건이 셋입니다.

  1. 자식이 할당된 자원의 한계치를 넘었을 때
  2. 자식에게 맡긴 작업이 더 이상 필요 없어졌을 때
  3. 부모가 종료할 때. 운영체제는 부모가 먼저 사라지는 것을 허용하지 않으므로, 자식부터 차례로 종료시킵니다

6. 협력하는 프로세스와 IPC

프로세스는 원칙적으로 서로의 주소 공간을 볼 수 없습니다. 각자 자기 일만 하면 독립적 프로세스이고, 데이터를 주고받아야 하면 협력 프로세스입니다.

협력하려면 벽을 넘을 방법이 필요합니다. 이것이 IPC(Inter-Process Communication)이며 크게 두 방법입니다.

방식message passingshared memory
전달 경로커널을 통해 메시지를 주고받음두 프로세스가 물리 메모리 일부를 함께 씀
커널 개입메시지마다 개입공유 공간을 만들 때만 개입
속도상대적으로 느림빠름
주의점구현이 단순동시 접근을 프로세스가 직접 조심해야 함

message passing은 수신자를 지정하는 방식에 따라 다시 둘로 나뉩니다. direct communication은 "프로세스 P에게 보낸다"처럼 상대를 직접 지정하는 방식이고, indirect communication은 메일박스(mailbox)에 넣어두면 누구든 꺼내 가는 방식입니다.

profile
ML Engineer 🧠 | AI 모델 개발과 최적화 경험을 기록하며 성장하는 개발자 🚀 The light that burns twice as bright burns half as long ✨

0개의 댓글