프로세스

프로그램 : 하드 디스크, USB 등에 저장된 실행 파일 프로세스 : 메모리에 적재되어 실행된 프로그램(대기상태 포함)

  • 프로세스의 특징
    • 운영체제에 의해 메모리에 적재된 프로그램으로, 실행에 필요한 메모리를 할당받고, 코드와 데이터 등을 적재한다
    • 서로 독립적인 메모리 공간을 가져 각자의 영역에 접근할 수 없다
    • 고유 번호(프로세스 ID)를 할당받는다
    • 실행-대기-잠자기-종료 와 같은 생명 주기를 가진다
    • 모든 프로세스 정보(프로세스 테이블에서)와 동작은 커널에 의해 관리된다
    • 하나의 프로그램을 여러번 실행하면 각각 독립된 프로세스가 생성되며, 이것들을 프로그램의 다중 인스턴스라고 부른다
      • 다중 인스턴스들은 코드가 동일하기 때문에, 효율적인 메모리 사용을 위해 코드가 적재된 메모리 영역을 공유한다
프로세스의 주소 공간
  • CPU의 주소공간과 같음(사용자 공간 + 커널 공간)
  • 프로세스의 크기 : 사용중인 코드 + 데이터 + 힙 + 스택을 합친 크기
  • 프로세스의 주소 공간은 가상 공간이다
    • 각각의 프로세스는 물리 메모리 여러 공간을 가상 주소 공간으로서 할당 받는다
    • 각 프로세스는 0번지에서 시작되어 개발자가 메모리 주소에 대한 고민 없이 개발이 가능하다
  • 힙 영역데이터 공간이 끝나는 주소에서 높은 주소로 채워짐
    • Heap Overflow
      • 힙 영역이 스택 영역과 충돌한 상황
  • 스택 영역사용자 공간의 끝 주소에서 낮은 주소로 채워짐
    • Stack Overflow
      • 할당된 스택 크기를 넘어서 프레임이 쌓이는 상황

프로세스 관리

커널공간에 생성되는 프로세스 테이블, 프로세스 제어블록을 사용해 관리한다

프로세스 테이블(Process Table)
  • 시스템 전체에 하나의 프로세스 테이블을 두고 모든 프로세스의 정보를 관리
    프로세스 제어 블록(PCB)
  • 프로세스를 생성할 때마다 PCB를 생성하여 정보를 저장
  • 프로세스 테이블에 PID(프로세스 번호)와 함께 연결
  • 저장 정보
    • 프로세스 번호(PID)
      • 고유한 프로세스 식별 번호
      • 0과 자연수만 사용
    • 부모 프로세스 번호(PPID)
      • 프로세스는 프로세스에 의해 생성되며 부모-자식 관계가 형성된다
    • 프로세스 상태 정보(Process State)
      • 지속적으로 변하는 프로세스의 상태를 저장
    • 프로세스 컨텍스트 정보(Process Context)
      • 컨텍스트 스위칭이 일어날 때, 중단되는 현재 프로세스의 컨텍스트를 저장
    • 스케줄링 정보
      • 프로세스 스케줄링에 사용되는 값들을 저장(프로세스 우선순위 등등)
    • 종료코드(exit code)
      • 프로세스 종료 시 부모 프로세스에게 전달하는 종료 이유를 담은 정수 값(C/C++/Java main 함수의 리턴값)
      • 해당 코드를 부모 프로세스가 읽지 않으면 종료되었지만 PCB와 프로세스 테이블에서 제거되지 않는 좀비(zombie) 프로세스가 된다(프로세스 목록 출력 시 좀비 상태로 출력됨)
    • 프로세스의 오픈 파일 테이블(Per-proccess open file table)
      • 프로세스 실행 중에 열어 놓은 파일 정보
      • 열어 놓고 프로세스가 종료되더라도 커널이 해당 파일들을 닫아줌
    • 메모리 관리를 위한 정보들
      • 매핑 테이블 주소 등
    • 프로세스 사이의 통신 정보들
      • 서로의 영역에 접근 불가이므로, 프로세스간 통신 방법을 저장
      • 신호 핸들러 리스트, 신호 플래그 등등
    • 회계 정보
    • 소유자 정보
    • 기타
프로세스 생명 주기와 상태 변이

여러 프로세스를 번갈아가며 실행하기 때문에, 상황에 따른 여러가지 상태가 존재한다

  • 프로세스의 일생

  • New(생성)
    • 프로세스가 시스템 호출을 통해 생성됨
    • 각종 정보들을 사용자 공간 및 커널 공간 등에 적재하고 프로세스 테이블에 등록
    • PCB에서 프로세스 상태를 New로 기록
  • Ready(준비)
    • 스케줄링을 기다리는 상태
    • New 상태에서 커널에 있는 준비 큐(ready queue)에 삽입될 때
    • Running 상태에서 할당 시간을 다 썼거나 스스로 다른 프로세스에게 양보할 때
    • 특정 작업으로 인해 Blocked 상태 였다가 작업이 완료 됐을 때
    • 기아 프로세스(starving process) : 잘못된 스케줄링으로 인해 준비 큐에 오래 머무르는 프로세스
  • Running(실행)
    • 스케줄링을 통해 선택된 프로세스가 CPU에 의해 실행중인 상태
  • Blocked / Wait(대기)
    • Running 상태에서 자원 요청, 입출력 요청에 의해 기다리는 상태
    • Running 상태에서 스케줄링을 통해 다른 프로세스와 컨텍스트 스위칭됨
    • 처리가 완료되면 Ready로 돌아감
  • Terminated/Zombie(좀비 상태)
    • 프로세스가 종료되었지만 부모 프로세스가 종료코드를 읽지 않은 상태
    • 종료코드가 담긴 PCB가 메모리와 프로세스 테이블의 항목에 남아 있음
  • Terminated/Out(종료)
    • 부모 프로세스가 좀비 상태의 자식 프로세스의 종료코드를 읽어갈 때
    • PCB를 시스템에서 제거하고 프로세스 테이블의 항목에서도 제거
스레드 스케줄링

CPU를 할당할 스레드를 결정하는 과정

요즘은 대부분 멀티스레드 운영체제이다

  • 스레드(thread)
    • 프로세스보다 작은 크기의 실행 단위
    • 운영체제에 의해 스케줄링됨
    • 멀티스레드 운영체제의 등장으로 프로세스는 스레드들에게 공유 자원을 제공하는 컨테이너로 바뀜
  • 프로세스 스케줄링을 하고 그 안의 스레드를 또 스케줄링 해야한다?
    • 이전에는 그랬으나 오늘날의 운영체제에선 아니다
    • 프로세스 선택 없이 시스템내의 스레드 전체를 대상으로 스레드 스케줄링(thread scheduling)을 실행한다

프로세스 계층 구조

프로세스는 프로세스에 의해 생성된다

  • 부모-자식 관계
    • 부모 프로세스
      • 프로세스를 생성한 프로세스
    • 자식 프로세스
      • 생성된 프로세스
    • #0 프로세스를 제외한 모든 프로세스는 부모 프로세스를 가진다
    • 부모 프로세스는 여러 개의 자식 프로세스를 가질 수 있다
  • 유휴 프로세스(idle process)(#0) (운영체제마다 부르는 이름이 다르다 @Unix : swapper @Linux : idle 프로세스)
    • 최상단의 시조 프로세스
    • 시스템 내에 스케줄링을 할 프로세스가 없을 때 실행(Ready 상태 프로세스가 없을 때)
    • 커널 공간에 존재하며 커널 모드에서 단순 루프를 돌며 시간을 보냄
      • 인터럽트 발생까지 CPU 클럭 속도를 줄이거나 절전 모드에 들어가도록 구현
  • init 프로세스(system 프로세스)(#1)
    • 부팅 과정에서 시스템을 초기화
    • 시스템 종료 과정도 책임짐
    • 사용자 모드에서 실행되는 모든 프로세스들의 조상
  • kthreadd(#2)
    • 부팅 시 커널에 의해 생성되며 커널 공간에서 커널 모드로 실행됨
    • 커널의 기능을 돕는 프로세스
  • 프로세스 관리 시스템 호출
    • 프로세스 생성, 관리, 종료는 운영체제가 시스템 호출을 통해서만 가능함
    • fork()
      • 자식 프로세스를 생성하는 시스템 호출 함수
    • exit()
      • 현재 프로세스의 종료를 처리하는 시스템 호출 함수
    • wait()
      • 부모가 자식 프로세스가 종료할 때 까지 기다리는 시스템 호출 함수

  • (a) : 정상적으로 종료된 자식 프로세스
  • (b) : 완전히 제거되지 않은 좀비 프로세스
  • 좀비 프로세스의 문제
    • 프로세스 테이블 항목의 제한으로 새로운 프로세스 생성이 불가할 수 있음
  • 고아 프로세스
    • 자신보다 부모 프로세스가 먼저 종료된 프로세스
    • 자동으로 init 프로세스가 부모 프로세스가 되어서 wait()를 호출해줌(부모 프로세스가 생겼지만 여전히 고아 프로세스임)
백그라운드 프로세스와 포그라운드 프로세스

사용자는 터미널을 통해 프로세스와 대화한다

  • 백그라운드 프로세스(background process)
    • 사용자와의 대화를 필요로 하지 않는 프로세스(사용자의 명령 없이 실행됨)
    • 대부분 특정 사건을 기다리며 idle 상태로 잠을 자거나 디스크에 스왑된 상태로 실행됨
  • 포그라운드 프로세스(foreground process)
    • 사용자의 입출력을 독점하는 프로세스
  • CPU 집중 프로세스/CPU 바운드 프로세스(CPU intensive process)
    • 계산 중심의 작업으로 CPU 활용이 많은 프로세스
  • I/O 집중 프로세스/I/O 바운드 프로세스(I/O intensive process)
    • 입출력 작업이 많은 프로세스
    • 입출력 대기 시간이 길어 CPU 사용 비중이 낮음

CPU 집중 vs I/O 집중

  • 프로세스 스케줄링 시 I/O 집중 프로세스의 우선순위가 높다
    • I/O 요청 대기 시간동안 다른 프로세스에 할당할 수 있기 때문

프로세스 제어

  • 프로세스 생성 과정
    • PID 번호 할당
      -> PCB 구조체 생성
      -> 프로세스 테이블에 새 항목 할당
      -> 테이블에 PCB 연결
      -> 메모리 공간 할당
      -> 메모리 공간에 코드, 데이터 적재
      -> PCB에 프로세스 정보 기록
      -> 프로세스 상태를 Ready로 표시하고 준비 큐에 삽입
  • 자식 프로세스를 생성하는 이유
    • 작업 분리를 통한 병렬 처리의 안전성
      • 독립된 메모리 공간을 가지기 때문에서로 다른 CPU 코어에서 병렬 실행이 가능하다
      • 독립된 메모리 공간을 가지는 프로세스는 문제가 발생하여도 다른 프로세스에 영향을 주지 않는다
      • ex) 웹 서버에서 각 클라이언트의 요청을 각각의 자식 프로세스를 생성하여 위임하고 다른 클라이언트의 요청을 기다림
    • 단점
      • 메모리와 리소스를 공유하지 않기 때문에 프로세스간 통신에 대한 비용이 증가한다
  • fork()
    • 현재 프로세스의 메모리를 복사형 자식 프로세스를 생성하는 시스템 호출
    • 리턴 값
      • 자식 프로세스 : 0
      • 부모 프로세스 : 자식 프로세스의 PID
      • 에러 : -1
  • 프로세스 오버레이(process overlay)
    • 현재 실행중인 프로세스 주소 공간에 새로운 응용프로그램을 적재하여 실행시키는 기법
    • exec() 시스템 호출 사용
  • exec()
    • 호출 프로세스의 주소공간에 새로운 응용프로그램의 사용자 공간 정보들을 그대로 올려 기존의 영역들은 사라진다
    • PID, PPID는 계승된다
    • exec 패밀리라고 부르는 함수들 중 적절한 것을 사용(예 : execlp(), execv(), execvp() 등)
  • exit()
    • 프로세스를 종료시키고 종료코드 상태를 부모 프로세스에게 전달한다
    • 할당된 모든 메모리와 자원을 반환하고 열어 놓은 파일, 소켓 등을 닫는다
    • PCB내의 프로세스 상태를 Terminated/Zombie 로 바꾸고 종료코드를 저장한다
  • wait()
    • 부모 프로세스에서 호출하는 시스템 함수이며, 자식 프로세스의 PCB에서 종료코드를 읽고 자식 프로세스의 PCB와 프로세스 테이블 내의 항목을 완전히 제거한다
    • 이 과정을 거쳐야 해당 프로세스가 완전히 사라진다

댓글남기기