운영체제

프로세스 제어: 생성부터 종료까지

addmean 2024. 8. 17. 14:51
이 포스팅에서는 프로세스 생성과 종료 과정, 그리고 이를 제어하는 방법에 대해 살펴보겠습니다.
 
 

1. 프로세스 생성의 다양한 시나리오

프로세스는 여러 가지 이유로 시스템 내에서 생성됩니다.

 

그 주요 사례는 다음과 같습니다:

  • 시스템 부팅: 시스템이 시작될 때 기본적으로 필요한 프로세스가 생성됩니다.
  • 사용자 로그인: 사용자가 로그인하면 그와 상호작용하기 위한 쉘 같은 프로세스가 생성됩니다.
  • 명령 실행: 사용자가 특정 명령을 입력하여 새로운 프로세스를 생성할 수 있습니다.
  • 배치 작업: at나 batch 명령을 사용해 배치 작업을 실행할 때 새로운 프로세스가 생성됩니다.
  • 시스템 호출: 프로그램 내에서 직접 시스템 호출을 통해 프로세스를 생성할 수 있습니다.

 

2. 프로세스 생성 과정

프로세스는 기존 프로세스에 의해 생성되며, 이 과정은 운영체제의 시스템 호출을 통해 이루어집니다.

  • PID 할당: 새 프로세스는 고유한 프로세스 ID(PID)를 부여받습니다.
  • PCB 생성: 프로세스 제어 블록(PCB)이 생성되어 프로세스의 상태와 정보를 관리합니다.
  • 메모리 할당: 새 프로세스를 위해 메모리가 할당되고, 코드와 데이터를 적재합니다.
  • 준비 큐 등록: 새 프로세스는 준비 상태로 표시되며, 준비 큐에 등록되어 스케줄링을 기다립니다.

 

3. 프로세스 복사: fork() 시스템 호출

리눅스에서 fork() 시스템 호출은 현재 프로세스를 복사하여 새로운 자식 프로세스를 생성합니다.

 

이때 부모와 자식은 거의 동일한 환경을 가지지만, 독립적인 주소 공간을 사용합니다.

int pid = fork();
if (pid == 0) {
    // 자식 프로세스에서 실행
} else {
    // 부모 프로세스에서 실행
}

 

4. 프로세스 오버레이와 exec()

 

fork()로 생성된 자식 프로세스는 때때로 부모 프로세스와 완전히 다른 프로그램을 실행해야 할 때가 있습니다.

 

이때 exec() 시스템 호출이 사용됩니다.

 

exec()는 현재 프로세스의 메모리 공간을 새로운 프로그램으로 덮어쓰지만, 프로세스의 PID는 그대로 유지됩니다.

 
execlp("/bin/ls", "ls", NULL);

 

5. 프로세스 종료와 자원 반환

 

프로세스가 종료되면, exit() 시스템 호출을 통해 시스템에 종료 상태를 알립니다.

 

이 과정에서 프로세스가 사용하던 모든 자원(메모리, 파일 등)은 운영체제로 반환되며, 프로세스는 Terminated 상태로 표시됩니다.

 

부모 프로세스는 자식 프로세스의 종료 상태를 wait() 시스템 호출로 읽어 들이며, 이를 통해 자식 프로세스의 PCB는 완전히 제거됩니다.

 

 

6. 좀비 프로세스와 고아 프로세스

  • 좀비 프로세스: 프로세스가 종료되었지만, 부모 프로세스가 그 종료 상태를 읽지 않았을 경우, 프로세스의 PCB가 남아있는 상태입니다. 이때 프로세스는 좀비 상태가 됩니다.
  • 고아 프로세스: 부모 프로세스가 종료된 후에도 자식 프로세스가 계속 실행되는 경우입니다. 고아 프로세스는 자동으로 init 프로세스가 입양하여 관리하게 됩니다.

 

결론

fork(), exec(), exit()와 같은 시스템 호출은 프로세스의 생명주기를 관리하며, 이를 통해 효율적인 프로세스 제어가 가능합니다.

프로세스 관리의 개념을 이해하면, 시스템 프로그래밍과 운영체제의 동작 방식을 더 깊이 이해할 수 있습니다.