All'alba vincerò

At dawn, I will win!

CS

프로세스 생성과 종료 & 프로세스 제어

나디아 Nadia 2025. 4. 24. 23:04

 

프로세스 생성 과정

  • 0번 프로세스 생성 과정
    • .exe 파일 실행 
      → 운영체제는 해당 프로그램의 코드 영역과 데이터 영역을 메모리에 로드함

      → 빈 스택과 힙 공간을 확보함 
      → 이 프로세스를 관리하기 위한 PCB를 생성하고 값을 초기화함
  • 이 과정은 운영체제가 부팅되고 0번 프로세스가 생성될 때 딱 1번 실행
    나머지 모든 프로세스는 0번 프로세스를 복사해서 사용
    → 복사는 fork() 함수를 이용함 (새로 만드는 것보다 복사가 더 빠름)

 

 

 

부모 / 자식 프로세스

자식 프로세스

: 0번 프로세스를 복사해서 만든 프로세스

  • 자식 프로세스는 부모 프로세스의 code, data, stack 영역과 PCB 내용을 전부 복사함

 

부모 프로세스

: 자식 프로세스 입장에서 0번 프로세스

  • 두 프로세스(부모, 자식)는 CPU 스케줄링에 따라 실행됨
    → 어떤 프로세스가 먼저 실행될지는 운영체제가 결정함

 

 


프로세스 제어 (Process Control)

 

Q. 0번 프로세스를 복사하면 똑같이 실행되는 것 아닌가?
→ A. 맞음

 

Q. 그럼 자기가 원하는 코드는 어떻게 실행시키는가?
→ A. exec() 함수를 실행시켜서 기존 부모의 code/data 영역을 원하는 코드로 덮어씀

 

 

 

fork() 함수

: 현재 실행 중인 프로세스를 복사해서 똑같은 새로운 프로세스를 하나 더 만드는 함수

    • 부모 프로세스: 1(0이 아닌 값)을 반환
    • 자식 프로세스: 0을 반환

 

 

 

wait() 함수

: 자식 프로세스에게서 exit() 신호가 올 때까지 기다리는 시스템 함수

  • 컨텍스트 스위칭을 통해 부모 프로세스에게 CPU가 할당되더라도
    자식 프로세스의 종료 신호가 오기 전까지는 다른 코드를 실행하지 않음

 

 

 

execlp() 함수

: 지정한 프로그램를 실행시키는 함수

  • 지정한 프로그램의 코드와 데이터를 가져와서 자식 프로세스를 덮어씀
    ⇒  이때, 자식 프로세스는 부모와 완전히 다른 프로세스가 됨
  • 실패 시 -1 반환, 성공 시 반환값 X

 

 

 

exit() 함수

= 자식 프로세스가 부모 프로세스에게 프로세스의 정상 종료를 알리는 함수

  • 부모 프로세스는 자식 프로세스의 Exit Status를 읽고 자식 프로세스를 정리함
  • 만약 부모가 먼저 종료되거나 자식이 비정상적으로 종료되어 exit() 신호를 보내지 못하면
    → Exit Status를 읽지 못해 메모리에 계속 살아있게 됨
    좀비 프로세스 발생

 

 

 

실행 흐름

  1. fork() 호출
    → 자식 프로세스 생성(복사)
    반환값으로 부모 프로세스엔 0이 아닌 값을, 자식 프로세스엔 0을 반환
  2. fork() 함수의 반환값으로 조건문 분기 실행
  3. 자식 프로세스
    • execlp() 호출
    • 만약 실패하면, exit(1)로 비정상 종료
  4. 부모 프로세스
    • wait() 호출 → 자식이 exit()하거나 exec()한 프로그램이 끝날 때까지 기다림
    • 자식이 종료되면 wait()이 반환됨 → 자식 프로세스 종료 확인
  5. 부모도 return 0;으로 종료
int main() {
    int pid = fork();  // 부모 → 자식 복사

    // 자식 프로세스
    if (pid == 0) {
        // 자식 프로세스 실행
        execlp("ls", "ls", "-l", NULL);

       // exec 실행 실패 시 실행
        exit(1);  
    }
    
    // 부모 프로세스 
    else if (pid > 0) {
        // 부모 프로세스 실행
        int status;
        wait(&status);  // 자식이 끝날 때까지 기다림
    }
    
    else {
        // fork 실패
        return 1;
    }

    return 0;
}