[OS] 프로세스의 연산

박시은·2023년 10월 19일
0

OS

목록 보기
10/27
post-thumbnail
post-custom-banner

▶ 프로세스 생성

프로세스를 새로 생성하는 방법뿐만아니라 실행중인 프로세스로부터 새로운 프로세스를 복사하는 방법도 있다.


▷ fork() 시스템 콜

fork() 시스템 콜이란?

  • fork() 시스템 호출은 실행 중인 프로세스를 복사본을 생성한다.
  • 부모 - 자식 관계가 형성되며, 생성된 자식 프로세스는 부모 프로세스와 동일한 메모리(같은 코드 및 데이터)를 가진다.
  • 부모와 자식 프로세스는 서로 다른 주소 공간을 가지므로, 한 프로세스에서 일어나는 메모리 변경이 다른 프로세스에 영향을 주지 않는다.

fork() 시스템 호출의 동작 과정

  • fork() 시스템 호출을 사용하면 실행 중인 프로세스와 똑같은 프로세스가 하나 더 만들어진다.
    (트리 구조 형성)
  • 단, PID가 변경된다.
  • fork() 성공시 반환 값
    • 부모 : 자식 프로세스의 PID
    • 자식 : 0

fork() 시스템 호출의 예⭐

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
    pid_t pid;

    /* 자식 프로세스 포크 */
    pid = fork();

    if (pid < 0) {	/* pid가 0보다 작으면 포크 실패 */
        fprintf(stderr, "Fork Failed");
        return 1;
    }
    else if (pid == 0) {	/* pid가 0이면 자식 프로세스 */
        execlp("/bin/ls", "ls", NULL);
    }
    else {	/* 부모 프로세스(양수) */
        /* 자식이 끝날 때(Termination)까지 부모는 대기함 */
        wait(NULL);
        printf("Child Complete");
    }

    return 0;
}


fork() 시스템 호출의 장점

  • 프로세스의 생성 속도가 빠르다.

    • 하드디스크로부터 프로그램을 새로 가져오지 않고 기존 메모리에서 복사하기 때문이다.
  • 추가 작업 없이 자원을 상속할 수 있다.

    • 부모 프로세서가 사용하던 모든 자원을 추가 작업 없이 자식 프로세스에 상속할 수 있다.
  • 효율적으로 시스템 관리를 할 수 있다.

    • 자식 프로세스가 종료되면 사용하던 자원을 부모 프로세스가 정리해주기 때문이다.



▶ 프로세스의 전환

▷ exec()

exec() 시스템 콜이란?

  • 프로세스는 그대로 둔 채 내용만 바꾸는 시스템 콜이다.
  • exec() 시스템 콜을 하면 현재의 프로세스가 완전히 새롭게 로드된 다른 프로세스로 전환된다.
  • 즉, 원래의 코드와 데이터가 사라져버리고 완전히 새롭게 로드된다. (호출 후 반환x)

exec() 시스템 콜의 장점

  • 프로세스의 구조체를 재활용할 수 있다.
  • 이미 만들어진 자원(PCB, 부모-자식 관계, 메모리 영역)을 재활용 할 수 있어 새로운 코드 영역만 가져오면 되기 때문에 OS 작업이 수월하다.
  • PID가 변경되지 않기 때문에, 프로세스가 종료된 후 부모 프로세스로 돌아올 수 있다.

exec() 시스템 호출의 예




▶ 프로세스 종료 (Process Termination)

▷ exit 시스템 콜

  • 부모가 자식을 강제 종료하는 경우 자식 프로세스를 다 죽이고 종료(abort() system call)
    • 자식에게 할당한 자원을 초과 사용하려는 경우
    • 자식에게 할당한 Task가 더 이상 필요하지 않을 때
    • 부모 프로세스가 exit할 경우

▷ 좀비 vs 고아⭐

부모 프로세스는 자원을 회수하기 위해 자식 프로세스가 끝날 때까지 기다려야한다.
하지만 프로세스가 종료된 후에도 비정상적으로 남아 있는 프로세스들을 좀비 프로세스 또는 고아 프로세스라고 한다


  • Zombie(좀비)
    • 자식 프로세스가 먼저 종료 되었지만, 부모 프로세스가 wait를 불러주지 않은 상태로 종료해 자식 프로세스의 종료 상태를 회수하지 못한 상태를 말한다.
    • 부모 프로세스는 좀비 프로세스의 생성을 방지하기 위해 wait()함수를 호출하여 상태를 회수해야 한다.
    • 💡컴퓨터를 오래 켜두면 왜 느려질까? 좀비 프로세스가 메모리를 차지하기 때문이다!
      따라서 프로세스가 종료되면 그 프로세스가 사용한 메모리 공간을 깨끗이 청소해야 한다.


  • orphan(고아)
    • 부모 프로세스가 기다리지 않고 먼저 종료된 상태를 말한다. (좀비보다 심각한 문제)
    • 고아 상태가 된 프로세스들은 PID 1인 init프로세스가 자식 프로세스의 부모가 된다.

▷ wait() 시스템 콜

  • 프로세스의 종료 상태와 PID를 반환하는 함수이다.
  • wait() 시스템 콜은 자식 프로세스가 끝날 때까지 부모 프로세스가 기다린다.
    • 즉, wait() 시스템 콜을 통해 좀비와 고아 프로세스 생성을 방지할 수 있는 것이다!



▶ 프로세스의 계층 구조

  • 운영체제는 프로세스를 효율적으로 관리하기 위해 init 프로세스를 가장 먼저 만든 다음, 나머지 프로세스를 init 프로세스의 자식으로 만들어 트리 구조를 이룬다.
  • init 프로세스는 fork() exec() 시스템 호출을 사용하여 자식 프로세스를 만든다.



✏️문제

▷ 문제 1

그림 3.30에 표시된 프로그램을 사용하여 LINE A에서 출력되는 내용을 설명하라.
『 Operating System Concept 10th 연습문제 3.1번 』

답 :[ PARENT: value = 5 ]

새로운 프로세스는 fork()로 생성되는데, 이때 새로운 프로세스는 원래 프로세스(부모)의 복사본이다.
원래 프로세스(부모)에서의 변경은 새로운 프로세스에 영향을 미치지 않기 때문에 A라인은 부모 프로세스의 공간이므로 자식 프로세스의 value+=15가 공유되지 않는다.

따라서 A행의 출력은"PARENT: value = 5"가 된다.
이는 부모 프로세스에서만 value 값이 5로 변경되고, 자식 프로세스에서는 변경이 없음을 의미한다.


▷ 문제 2

최초의 부모 프로세스를 포함하여 그림 3.31 에 표시된 프로그램에 의해 몇 개의 프로세스가 생성되는가?
『 Operating System Concept 10th 연습문제 3.2번 』

답 :[ 8개의 프로세스 ]

fork()가 호출되면 프로세스 복제되어 새로운 자식 프로세스가 생성된다.

초기 부모프로세스 1개
첫 번째 fork()를 호출하면, 현재 실행 중인 프로세스가 복제되어 총 프로세스 2개
두 번째 fork()를 호출하면, 현재 실행 중인 모든 프로세스(2개)가 복제되어 총 프로세스 4개
세 번째 fork()를 호출하면, 현재 실행 중인 모든 프로세스(4개)가 복제되어 총 프로세스 8개

이를 통해 fork()는 자식 프로세스들을 생성하고 또 다시 fork를 하면 전에 생성된 자식프로세스들도 자식을 낳는 것을 확인할 수 있다. 즉 2의 3승(2^2^2) 이 되는 것이다


▷ 문제 3

프로세스가 fork() 연산을 사용하여 새로운 프로세스를 생성할 때 다음 중 어떤 상태가 부모 프로세스와 자식 프로세스 간에 공유되는가?
『 Operating System Concept 10th 연습문제 3.5번 』

  • A. 스택
  • B. 힙
  • C. 공유 메모리 세그먼트

답 :[ C ]

fork()가 호출되면 프로세스는 부모 프로세스의 메모리를 복사하기 때문에 각 프로세스마다 갖는 stack, heap, data, code 영역은 공유되지 않고, 공유 메모리 세그먼트만 공유가 된다.




📎참조

profile
블로그 이전했습니다!
post-custom-banner

0개의 댓글