TIL

[TIL/혼공컴운] 2025/02/17

프로세스와 스레드 ✍️프로그램이 실행되기 전까지, 보조기억장치에 위치한 프로그램은 그저 데이터 덩어리에 불과하다. 보조기억장치에 저장된 프로그램이 메모리에 적재되고 실행되는 순간, 프로그램은 프로세스가 되었다고 볼 수 있다.유닉스(Unix) 기반의 운영체제를 사용하는

2025년 2월 17일4min read

프로세스와 스레드 ✍️

1. 프로세스 개요 🌿

1-1. 프로세스 확인하기 ⚙️

프로그램이 실행되기 전까지, 보조기억장치에 위치한 프로그램은 그저 데이터 덩어리에 불과하다. 보조기억장치에 저장된 프로그램이 메모리에 적재되고 실행되는 순간, 프로그램은 프로세스가 되었다고 볼 수 있다.

유닉스(Unix) 기반의 운영체제를 사용하는 macOS에서 ``ps aux`` 명령어로, 실행 중인 프로세스들을 확인할 수 있다.

프로세스는 위 이미지와 같이, 포그라운드 프로세스 / 백그라운드 프로세스로 나뉜다.

특히 백그라운드 프로세스 중에서도 사용자와 상호작용하는 프로세스를 인터랙티브 백그라운드 프로세스라고 한다. 공식적인 명칭은 아니다.

사용자와 상호작용하지 않고 수행되는 백그라운드 프로세스를 macOS와 같은 유닉스 체계의 운영체제에서는 데몬이라고 칭하고, 윈도우 체계의 운영체제에서는 서비스라고 부른다.

포그라운드 프로세스는 내가 직접 요리를 하는 것이고, 인터랙티브 프로세스는 전자레인지를 돌려놓고 TV를 보는 것이며, 데몬은 냉장고가 자동으로 온도를 조절해 주는 모습이라고 볼 수 있다.

1-2. 프로세스 제어 블록 ⚙️

CPU라는 한정된 자원을 사용하기 위해서, 프로세스들은 차례로 돌아가며 한정된 시간만큼만 CPU를 사용하게 된다. 이때 운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하기 위해 프로세스 제어 블록(PCB; Process Control Block)이라는 자료 구조를 활용하게 된다.

PCB는 프로세스를 식별하기 위한 일종의 태그와 같다. PCB는 커널 영역에 생성되고, ``PID, 레지스터 값, 프로세스 상태, CPU 스케줄링 정보, 메모리 관리 정보, 사용한 파일과 입출력장치 목록``과 같은 정보들이 담겨 있다.

1-3. 문맥 교환 ⚙️

Context Switching에서 핵심은 아무래도 Context다. 문맥이란, 하나의 프로세스 수행을 재개하기 위해 기억해야 할 정보다. 앞서 설명한 PCB를 문맥으로 치환해서 생각해도 된다.

기존 프로세스의 문맥을 PCB에 백업하고, 새로운 프로세스를 실행하기 위해 문맥을 PCB로부터 복구하여 새로운 프로세스를 실행하는 과정을 "context를 switching"한다고 표현한다.

1-4. 프로세스의 메모리 영역 ⚙️

프로세스가 생성되면 커널 영역에 PCB가 생성된다. 그렇다면 사용자 영역에는 프로세스가 어떻게 배치되는 것인지 확인해야 한다.

목적에 맞게 네 가지 영역으로 나누어서 프로세스가 배치된다.

프로세스는 실행 중인 프로그램을 의미하며, 보조기억장치에 있는 프로그램이 메모리에 적재될 때 프로세스로 변환된다. 실행 방식에 따라 사용자와 직접 상호작용하는 포그라운드 프로세스, 백그라운드에서 실행되지만 필요하면 조작할 수 있는 인터랙티브 백그라운드 프로세스, 그리고 사용자의 개입 없이 지속적으로 실행되는 데몬(Unix) / 서비스(Windows)로 구분된다. 운영체제는 프로세스의 실행 정보를 프로세스 제어 블록(PCB)에 저장하며, CPU가 다른 프로세스로 전환될 때 기존 프로세스의 상태를 저장하고 새 프로세스를 복원하는 문맥 교환(Context Switching)을 수행한다. 프로세스의 메모리 공간은 실행 코드가 저장되는 코드(Code) 영역, 전역 및 정적 변수를 저장하는 데이터(Data) 영역, 동적 메모리가 할당되는 힙(Heap) 영역, 함수 호출 시 지역 변수와 매개변수를 저장하는 스택(Stack) 영역으로 구성된다.

2. 프로세스 상태와 계층 구조 🌿

2-1. 프로세스 상태 ⚙️

PCB에 현재 프로세스의 상태가 기록된다고 했는데, 프로세스의 상태에는 다섯 가지가 있다. 한 장의 이미지로 표현할 수 있다.

프로세스가 대기 상태가 되는 이유에 입출력 작업만 있는 것은 아니지만, 프로세스가 대기 상태가 되는 대부분의 원인이 입출력 작업에 있기에, '프로세스가 입출력 작업을 하면 대기 상태가 된다'라고 생각해도 무방하다.

2-2. 프로세스 계층 구조 ⚙️

프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있다. 부모 프로세스로부터 자식 프로세스가 생성된다고 표현할 수 있고, 많은 운영체제에서 이처럼 프로세스가 프로세스를 낳는 계층적 구조로 프로세스들을 관리한다.

사용자가 컴퓨터를 켠 뒤 로그인 창을 통해 로그인에 성공한 뒤, bash 셸로 Vim이라는 문서 편집기 프로그램을 실행한 상황을 표현한 도식이다.

최초 프로세스가 로그인 프로세스를 자식 프로세스로 생성한 뒤, 로그인 프로세스는 자식 프로세스로 bash 프로세스를 생성하고, bash 프로세스는 Vim 프로세스를 생성한 셈이라고 볼 수 있다.

2-3. 프로세스 생성 기법 ⚙️

부모 프로세스가 자식 프로세스를 만들어내는 과정, 그리고 자식 프로세스가 자신만의 코드를 실행하는 과정을 살펴보고자 한다. 이 또한 한 장의 그림으로 설명 가능하다.

fork()와 exec()는 기본적으로 시스템 호출이다.

부모 프로세스는 fork()를 통해 자기 자신 프로세스의 복사본을 만든다. 따라서 자식 프로세스는 부모 프로세스의 자원들을 상속받는다.

자식 프로세스는 이후 exec()를 통해 자신의 메모리 공간을 새로운 프로그램으로 덮어쓴다. exec()를 호출하면 코드 영역과 데이터 영역의 내용이 실행할 프로그램의 내용으로 변경되고, 나머지 영역은 초기화된다.

한마디로, 프로세스 계층 구조를 이루는 과정은 fork()와 exec()가 반복되는 과정으로 이해할 수 있다. fork()를 통해 부모의 옷을 물려받고, exec()를 통해 자식이 새로운 옷으로 갈아입는 과정이라고 비유할 수 있다.

만약 부모 프로세스가 자식 프로세스를 fork() 한 뒤, 누구도 exec()를 호출하지 않으면, 부모 프로세스와 자식 프로세스는 같은 코드를 병행하여 실행하는 프로세스가 된다.

3. 스레드 🌿

3-1. 멀티프로세스와 멀티스레드 ⚙️

프로세스는 실행 중인 프로그램이다. 스레드는 프로세스 내의 흐름이다. 흐름이 2개 이상이면 멀티 스레드라고 표현할 수 있다.

우선 여러 프로세스를 동시에 실행하는 것과 여러 스레드로 실행하는 것의 차이를 인지하는 것이 좋다.

"hello minkwan"을 출력하는 프로그램이 있다면 좌측의 이미지는 fork()를 세 번 진행한 상황이다. 동일한 내용을 스레드를 세 개 만들어 실행해도 동일한 결과를 얻을 수 있다.

프로세스끼리는 자원을 공유하지 않지만, 스레드는 같은 프로세스 내의 자원을 공유한다는 것이 핵심 of 핵심이다.

좌측 이미지, 그러니까 멀티 프로세스를 더 자세히 살펴보면 다음과 같다.

PID나 저장된 메모리 주소 등을 제외하면 모든 것이 동일한 프로세스 두 개가 통째로 메모리에 저장되는 모습이다. 같은 프로그램을 실행하기 위해 메모리에 동일한 내용들이 중복되어 존재하는 것이기에 메모리 낭비라고 볼 수 있다.

그렇다면 멀티 스레드의 핵심의 목표는 같은 프로세스 내의 자원을 공유하여 메모리 낭비를 최소화하는 것이 되겠다.

멀티 프로세스가 자원을 공유하지 않기에 독립적으로 실행되는 반면, 멀티 스레딩 방식은 공유하는 자원이 있기에 협력과 통신에 유리하다는 장점이 있다. 자원을 공유한다는 것이 항상 장점이 된다고 보긴 어렵다. 하나의 스레드에 문제가 생기면 프로세스 전체에 문제가 생길 수 있기 때문이다.

IPC나 공유 메모리 등에 대해서도 이야기해야 한다. 워낙 중요한 내용이라, 운영체제 전체에 대한 정리가 끝나면 외전(外傳)으로 다룰 생각이다.

회고 ✍️

많은 기술이나 혹은 그 기술에 대한 논의가 갈수록 복잡해진다. 무엇이든 어느 정도의 수준까지 가기 위해서 복잡성을 완전히 배제할 수는 없는 것이 사실이다.

그럼에도 읽는 것, 보는 것, 듣는 것, 모든 것을 단순하게 만들려고 노력한다. 그 일환으로, 한 장의 이미지로 표현하는 행위에 공을 들이곤 한다.

단순함에서 오는 신뢰의 힘을 믿는다. 복잡함은 단순함으로의 과정일 뿐이라는 사실을 인지하는 것이 중요하다. 복잡함을 추상화해낸 단순함을, 사람들은 클래식이라고 부르는 것 같기도 하다. 심플 이즈 더 어쩌구.