운영체제/OSTEP

프로세스의 개념

먹보 개발자 2025. 1. 3. 20:08

1. 프로세스의 정의

프로세스(Process): 운영체제가 제공하는 핵심 개념 중 하나로, 실행 중인 프로그램을 의미한다. 프로그램은 디스크에 저장된 명령어와 정적 데이터의 집합이며, 운영체제는 이를 메모리에 로드하여 실행 가능하게 만든다.

실행 중인 프로그램: 사용자들은 웹 브라우저, 메일 프로그램, 게임, 음악 플레이어 등 여러 프로그램을 동시에 실행시킴으로써 시스템을 효율적으로 사용할 수 있다. 운영체제는 이러한 다중 프로세스를 관리하여 사용자에게 원활한 경험을 제공한다.

 

2. 핵심 질문: CPU가 여러 개 존재한다는 환상을 어떻게 제공하는가?

가상화(Virtualization): 운영체제는 실제로는 하나 또는 소수의 물리적 CPU를 여러 개의 가상 CPU로 분할하여 다수의 프로세스가 동시에 실행되는 것처럼 보이게 한다.

시분할(Time Sharing): 운영체제는 프로세스 간에 CPU 시간을 빠르게 전환하면서 각 프로세스가 CPU를 독점적으로 사용하는 것처럼 느껴지도록 한다. 이를 통해 다중 프로세스가 효율적으로 CPU를 공유할 수 있게 한다.

문맥 교환(Context Switch): 운영체제가 프로세스 간에 전환할 때 현재 실행 중인 프로세스의 상태(레지스터 등)를 저장하고, 다음 실행할 프로세스의 상태를 복원하는 작업.

 

3. 프로세스 API

생성(Create): 새로운 프로세스를 생성하는 인터페이스를 제공. 예를 들어, 쉘에서 명령어를 입력하거나 프로그램 아이콘을 더블 클릭하면 운영체제가 새로운 프로세스를 생성한다.

제거(Destroy): 실행 중인 프로세스를 종료시키는 인터페이스를 제공. 사용자가 필요에 따라 프로세스를 중단시킬 수 있도록 한다.

대기(Wait): 특정 프로세스가 종료될 때까지 기다리는 인터페이스를 제공. 부모 프로세스가 자식 프로세스의 종료를 기다리는 경우 등이 이에 해당.

제어(Miscellaneous Control): 프로세스를 일시정지하거나 재개하는 등의 다양한 제어 기능을 제공.

상태(Status): 프로세스의 현재 상태(실행 중, 준비, 대기 등)를 조회할 수 있는 인터페이스를 제공.

 

4. 프로세스 생성의 세부 과정

프로그램 로드: 운영체제는 디스크에 저장된 프로그램의 코드와 정적 데이터를 메모리에 로드한다. 현대 운영체제는 필요한 시점에 필요한 부분만 로드하는 지연 로딩(lazy loading)을 사용하기도 한다.

메모리 할당: 스택(Stack)과 힙(Heap) 메모리를 할당하여 함수 호출과 동적 메모리 할당을 지원한다.

입출력 초기화: 프로세스가 표준 입력(STDIN), 표준 출력(STDOUT), 표준 에러(STDERR)와 같은 기본 입출력 스트림을 사용할 수 있도록 초기화한다.

실행 시작: 모든 초기화가 완료되면, 운영체제는 프로세스의 시작 지점(main 함수)으로 제어를 넘겨 프로그램 실행을 시작한다.

 

5. 프로세스 상태

실행(Running): 프로세스가 CPU에서 실행 중인 상태.

준비(Ready): 프로세스가 실행을 기다리고 있는 상태로, CPU를 사용할 준비가 되어 있음.

대기(Blocked): 프로세스가 입출력과 같은 외부 이벤트를 기다리느라 실행을 중단한 상태.

좀비(Zombie): 프로세스가 실행을 마쳤지만, 부모 프로세스가 종료 상태를 수집하지 않아 메모리에 남아 있는 상태.

프로세스 상태 전이: 프로세스는 준비 상태와 실행 상태 사이를 오가며, 입출력 요청 시 대기 상태로 전환된다. 이벤트가 발생하면 다시 준비 상태로 돌아와 실행될 수 있다.

 

6. 자료 구조: 프로세스 리스트와 PCB

프로세스 리스트(Process List): 현재 시스템에서 실행 중인 모든 프로세스를 관리하기 위한 자료 구조.

프로세스 제어 블럭(Process Control Block, PCB): 각 프로세스에 대한 정보를 저장하는 구조체로, 프로세스의 상태, 메모리 정보, CPU 레지스터 상태, 파일 디스크립터 등 다양한 정보를 포함한다.

 

예시 (xv6 Proc 구조체):

struct proc {
    char *mem;                  // 프로세스의 메모리 공간
    uint sz;                    // 프로세스의 메모리 크기
    char *kstack;               // 프로세스의 커널 스택
    enum proc_state state;      // 프로세스 상태
    int pid;                    // 프로세스 ID
    struct proc *parent;        // 부모 프로세스
    void *chan;                 // 대기 채널
    int killed;                 // 종료 여부
    struct file *ofile[NOFILE]; // 열린 파일 리스트
    struct inode *cwd;          // 현재 작업 디렉토리
    struct context context;     // 프로세스의 레지스터 상태
    struct trapframe *tf;       // 트랩 프레임
};

 

설명:

mem: 프로세스의 메모리 공간을 가리킴.

sz: 프로세스 메모리의 크기.

kstack: 커널 모드에서 사용하는 스택.

state: 프로세스의 현재 상태(UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE).

pid: 프로세스의 고유 식별자.

parent: 부모 프로세스를 가리킴.

chan: 프로세스가 대기 중인 이벤트 채널.

killed: 프로세스가 종료 요청을 받았는지 여부.

ofile: 열린 파일 리스트.

cwd: 현재 작업 디렉토리.

context: 문맥 교환 시 저장되는 레지스터 상태.

tf: 트랩 프레임으로, 시스템 콜이나 인터럽트 시점의 상태를 저장.

 

7. 요약

프로세스 관리의 중요성: 운영체제는 다중 프로세스를 효율적으로 관리하여 사용자에게 원활한 컴퓨팅 환경을 제공한다.

가상화와 시분할: 운영체제는 가상화를 통해 물리적 자원을 추상화하고, 시분할 기법을 통해 다중 프로세스가 동시에 실행되는 것처럼 보이게 한다.

프로세스 상태와 전이: 프로세스는 실행, 준비, 대기 등의 상태를 가지며, 운영체제는 이러한 상태 전이를 관리하여 자원을 효율적으로 분배한다.

자료 구조의 역할: PCB와 프로세스 리스트와 같은 자료 구조는 운영체제가 프로세스를 추적하고 관리하는 데 필수적이다.

'운영체제 > OSTEP' 카테고리의 다른 글

운영체제 개요  (1) 2025.01.03