프로세스 관리
포스트
취소

프로세스 관리

프로세스 내용이 길어서 두 개로 나눠서 씁니다.
이번 장은 프로세스 관리 ㄷㄱㄷㄱ…

KOCW 공개 강의: 반효경, 운영체제와 정보기술의 원리



프로세스 생성

  • 부모 프로세스가 자식 프로세스 생성 - 복제 생성
    -> 운영체제에게 시스템 콜 fork()을 통해 자식 프로세스 생성을 요청합니다.

  • 프로세스의 계층 구조(트리) 형성

  • 프로세스는 자원을 필요로 함
    -> 운영체제로부터 자원을 받고 부모와 자원을 공유한다.

  • 수행(Execution)
    (1) 부모와 자식은 공존하며 수행되는 모델

    (2) 자식이 종료될 때까지 부모가 기다리는(blocked) 모델

  • 주소 공간

    • 자식은 부모의 공간을 복사 (binary and OS data)

    • 자식은 그 공간에 새로운 프로그램을 올림
      → Data와 Stack가 똑같이 복사가 되므로 함수 실행 위치, 전역 변수, 프로그램 카운터 등이 모두 동일해집니다.

    • fork를 통해 복제 생성을 하고 다른 프로그램을 돌리고 싶다하면 exec() 시스템 콜을 통해 새 프로그램을 메모리에 덮어씌워 올립니다.


프로세스 종료

  • 프로세스가 자발적으로 exit 시스템 콜을 통해 정상 종료되는 경우
    프로세스가 마지막 명령을 수행 한 후 운영체제에게 이를 알려줍니다.(exit)

    (1) 자식이 부모에게 output data를 보냅니다.
    (2) 프로세스의 각 자원들이 운영체제에게 반납됩니다.

  • 부모가 자식 프로세스의 수행을 종료 시키는 경우

    • 자식이 할당 자원의 한계치를 넘어섬

    • 자식에게 할당된 태스크가 더 이상 필요하지 않음

    • 부모가 종료(exit)하는 경우
      운영체제는 부모 프로세스가 종료하는 경우 자식이 더 이상 수행되도록 두지 않음.
      단계적인 종료.


프로세스와 관련된 시스템 콜

1
2
3
4
1. fork() 
2. exec()
3. wait()
4. exit()


fork() 시스템 콜

운영체제에게 자식 프로세스 생성 요청을 하는 함수.

1
2
3
4
5
6
7
8
int main() {
    int pid; // pid > 0 이면 부모 프로세스, pid = 0이면 자식 프로세스.
    pid = fork(); 
    if(pid == 0) 
    	printf("Hello I'm child")
    else if(pid > 0)
    	printf("Hello I'm parent")
}

위에서 아래로 실행하다가 fork()를 만나면 똑같은 코드를 가진 pid가 0인 자식 프로세스가 만들어집니다.

기존의 부모 프로세스는 pid > 0인 로직을 타고 자식 프로세스는 pid가 0인 로직을 동시에 타게 됩니다.


exec() 시스템 콜

자식 프로세스에게 새로운 프로그램으로 덮어 씌우는 함수.

아래 예시를 보면 Hello 1을 출력한 후 exec가 실행되어 덮어졌으므로 기존 코드인 Hello 2는 출력 되지 않습니다.

1
2
3
4
5
6
int main() {
    printf("Hello 1")
    execlp("/bin/date", "bin/date", (char *)0); // bin/date: 현재 시간 날짜를 출력
    printf("Hello 2")
}
// Hello 1

보통 자식 프로세스를 생성한 후 부모와 다른 로직을 실행 시키려는 용도로 쓰기 때문에 하단과 같이 씁니다.

1
2
3
4
5
6
7
8
9
10
int main() {
    int pid;
    pid = fork() // 자식 프로세스 생성
    if(pid == 0) {
        printf("Hello I'm child\n")     
        execlp("ls", "ls", "-l", (char *)0); // 리눅스 명령어 ls -l 실행
    } else if(pid > 0) {
        printf("Hello I'm parent")
    }
}


wait() 시스템 콜

프로세스 A가 wait() 시스템 콜을 호출하면

  1. 커널은 자식 프로세스가 종료 될 때까지 프로세스 A를 sleep 시킨다 (block 상태)
  2. 자식 프로세스가 종료되면 커널은 프로세스 A를 깨운다 (ready 상태)
1
2
3
4
5
6
7
8
9
10
11
int main {
    int pid;
    pid = fork();

    if(pid == 0) {
        printf("Hello I'm child\n")
    } else {
        printf("Hello I'm parent")
        wait();
    }
}

예를 들어, vi A 커맨드를 통해 vi 에디터를 실행시키면 vi 에디터가 자식 프로세스의 형태로 실행이 됩니다.

이 때 부모 프로세스는 blocked 상태에 있다가 vi 에디터가 종료가 되면 다시 깨어나서 명령어를 입력받을 수 있는 상태가 됩니다.


exit() 시스템 콜

프로세스를 종료 시키는 시스템 콜.

  • 자발적 종료
    • 마지막 statement를 수행 후에 exit() 시스템 콜을 호출
    • 프로그램에 명시적으로 적지 않아도 main 함수가 리턴되는 위치에 컴파일러가 넣어줍니다.
  • 비자발적 종료
    • 부모 프로세스가 자식 프로세스를 강제 종료 시키는 경우
    • 키보드로 kill, break 등을 입력한 경우
    • 부모가 종료되는 경우 : 부모 프로세스가 종료하기 전에 자식들이 먼저 종료.



프로세스 간 협력

  • 독립적 프로세스
    프로세스는 각자의 주소 공간을 가지고 수행되므로 원칙적으로 하나의 프로세스는 다른 프로세스의 수행에 영향을 미치지 못합니다.

  • 협력 프로세스
    프로세스의 협력 메커니즘을 통해 하나의 프로세스가 다른 프로세스의 수행에 영향을 미칠 수 있습니다.

  • 프로세스 간 협력 메커니즘(IPC: Interprocess communication)

    • 메시지를 전달하는 방법
      message passing : 커널을 통해 다른 프로세스에게 메시지 전달

    • 주소 공간을 공유하는 방법
      shared memory : 서로 다른 프로세스 간에도 일부 주소 공간을 공유하게 함.

      (참고) thread
      쓰레드는 사실상 하나의 프로세스이므로 프로세스 간의 협력으로 보기는 어렵지만,
      동일한 프로세스를 구성하는 쓰레드 간에는 주소 공간을 공유하므로 협력이 가능합니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.
인기 태그
바로가기

프로세스의 개념과 상태

CPU 스케줄링

인기 태그