이 글은 건국대학교 2024년 1학기 운영체제 수업과 『Operating Systems: Three Easy Pieces』 를 참고하여 작성되었습니다.
『Operating Systems: Three Easy Pieces』
3장. dialogue : 가상화에 관한 대화
4장. 프로세스 개념
5장. 프로세스 API
프로그램은 디스크에 저장된 실행 가능한 파일(Executable File) 형태로 존재합니다. 이 파일은 컴파일된 코드 즉, 명령어(instruction)와 정적 데이터(static data)의 집합으로 이루어져 있습니다.
실행 파일이 메모리에 적재되어 실행될 때, 이를 프로세스라고 합니다. 각각의 프로세스는 독립된 메모리 공간을 할당받으며, 각각 다양한 machine state를 갖습니다. 이 상태에는 메모리, 레지스터 등이 포함됩니다.
: system call 복습
생성 : fork() 시스템 콜 함수는 새로운 자식 프로세스를 생성하는 시스템콜 함수입니다.
대기 : wait() 시스템 콜 함수는 부모 프로세스가 자신의 자식 프로세스 중 하나라도 종료될 때까지 대기하는 데 사용됩니다. 해당 함수를 사용하면 자식 프로세스가 먼저 종료하도록 순서 지정이 가능해집니다. 만약 특정 자식 프로세스를 기다리고 싶다면 waitpid() 시스템 콜 함수를 사용하면 됩니다.
실행 : 프로세스를 새롭게 생성하는 fork와 다르게 exec() 시스템 콜 함수는 프로세스가 특정 명령어 (다른 실행파일) 를 실행하도록 합니다. 새롭게 생성된 자식 프로세스에서 주로 사용되며, 현재 실행 중인 프로세스를 다른 프로그램으로 대체합니다.
CPU 가상화란, 마치 CPU가 여러개인 것처럼 변환하여 동시에 여러 개의 프로그램을 실행시키는 것을 의미합니다. 이를 통해 CPU를 효율적으로 사용할 수 있습니다.
CPU 가상화에서 시분할 기법은 여러 프로세스가 CPU 자원을 공유할 수 있도록 합니다. 각 프로세스는 할당된 시간만큼만 CPU를 사용하고, 시간이 만료되면 다음 프로세스에게 자원을 넘겨줍니다. 이 때 발생하는 프로세스 간 전환을 context switch 라고 합니다.
프로세스의 상태는 크게 Running, Ready, Blocked 3가지로 분류됩니다.
프로세스가 CPU자원을 할당받아 실행될 때 Running 상태가 됩니다.
프로세스가 CPU 자원을 할당받지 못해 대기하고 있을 상태를 Ready 상태라고 합니다.
프로세스가 특정 작업, 특히 I/O 작업을 수행중일 때, 해당 프로세스의 상태를 Blocked 상태로 설정합니다. 이 상태는 프로세스가 네트워크 장치나 디스크 같은 저장 장치로부터 데이터를 요청하고 그 작업이 완료될 때까지 지속됩니다. 프로세스가 I/O 작업을 마치면 Ready 상태로 전환되어 CPU 자원을 다시 할당받을 준비를 합니다.
(프로세스는 처음 생성될 때 ready 상태로 설정됩니다.)
- blocked 상태에서 ready 상태가 되는 과정I/O 작업을 마치면 I/O 디바이스가 인터럽트를 생성하여 OS의 interrupt-handler가 호출됩니다. 이 핸들러가 CPU 스케줄러에게 요청함으로써 프로세스의 상태가 Ready로 변경됩니다.
OS는 각 프로세스의 상태를 관리하기 위해, 모든 프로세스가 생성될 때마다 해당 프로세스만을 위한 PCB 자료구조도 함께 생성합니다. PCB의 한 예로, linux에서 사용되는 task_struct 구조체를 살펴보겠습니다.
struct task_struct {
volatile long state; // TASK_RUNNING, TASK_INTERRUPTIBLE, ..
void *stack; // 프로세스가 실행되는 동안 호출한 함수의 위치를 저장하는 곳
unsigned int cpu; // 현재 본인이 돌고 있는 CPU 코어의 번호를 저장하는 변수
struct mm_struct *mm; // memory virtualization을 하기 위한 정보를 포함하는 구조체
struct task_struct *parent; // parent의 pcb를 가리킴
struct list_head children;
struct files_struct *files; // 이 프로세스가 오픈한 모든 파일들에 대한 정보를 저장
}
state
리눅스에서는 state 변수에 ready 상태가 따로 존재하지 않습니다. 따라서 running 상태와 ready 상태 모두 state = TASK_RUNNING 으로 두고, 다른 변수를 통해 CPU 자원을 할당받았는지 구분합니다. 또한 리눅스에는 blocked 상태의 종류가 다양합니다.
stack
user-mode의 스택과 kernel-mode에서의 스택이 따로 존재합니다. (추후 다룰 예정)
cpu : 해당 프로세스가 돌고 있는 CPU 코어의 번호를 저장하는 변수입니다.
mm : 메모리 가상화를 위한 정보를 포함하는 구조체를 가리킵니다.
parent : 해당 프로세스의 부모 프로세스를 가리킵니다.
children : 해당 프로세스의 자식 프로세스를 circular doubly linkedlist 를 사용하여 관리합니다.
files : 이 프로세스가 오픈한 모든 파일들에 대한 정보를 저장
OS는 모든 프로세스들의 상태를 파악하고 관리하기 위해 각 상태마다 큐를 두고, 큐에 모든 프로세스들의 PCB를 집어넣습니다. (이름은 큐이지만 다른 자료구조를 사용할 수도 있습니다. 대표적으로 linux에서는 red-blak tree를 사용합니다.)