시작하기 앞서
이 글은 웹 백엔드 주니어 개발자가 인프런의 그림으로 쉽게 배우는 운영체제 강의를 들으며 공부한 내용을 러프하게 정리한 글입니다.
프로그램과 프로세스
- 프로그램(Program): 하드디스크 등에 저장된 명령문의 집합체
- 프로세스(Process): 실행 중인 프로그램 (하드디스크에 있는 프로그램이 메모리에 올라가면 실행 중인 프로그램, 즉 프로세스가 된다!)
프로세스의 구조
- code, data, heap, stack
- code: 컴파일된 소스코드가 저장되는 영역. 즉, 프로그램 자기 자신. 중간에 소스가 변경되지 않도록 read only로 저장됨
- data: 전역/static 변수가 할당되는 영역. java의 클래스 정보도 data 영역에 할당되는 것으로 아는데 정확하지 않음 (아닐수도 있음..)
- heap: 프로그래머가 할당/해제하는 메모리 영역. 동적으로 할당되는 메모리가 저장되는 영역이며 java의 경우 Garbage Collection이, c 같은 경우는 프로그래머가 직접 이 영역을 관리해주어야 한다.
- 함수/지역변수 등 '임시'적인 데이터가 저장되는 영역. 그 유명한 stack overflow가 이 stack을 말하는 것.
Uni Programming vs Multi Programming vs Multi Processing
- 유니프로그래밍과 멀티프로그래밍은 메모리 관점에서 정의하는 용어
- 멀티프로세싱은 CPU 관점에서 정의하는 용어
- 유니프로그래밍: 메모리에 단 하나의 프로세스만 올라갈 수 있다. (과거에는 메모리 크기가 작았기 때문에 단 하나의 프로세스만 메모리에 올려 사용했음.)
- 멀티프로그래밍: 메모리에 여러 개의 프로세스가 동시에 올라갈 수 있다. (현재는 대부분 이 방식 사용)
- 멀티프로세싱: CPU가 여러 개의 프로세스를 처리할 수 있다. (ex. 시분할)
- 현재는 대부분 멀티프로그래밍 + 멀티프로세싱 사용
프로세스 제어 블록 (PCB, Process Control Block)
- 일종의 자료구조?로 '운영체제가 프로세스를 표현하는 방식'
- 프로세스의 정보를 담은 블록으로 운영체제는 PCB 내의 정보를 바탕으로 프로세스를 제어
- PCB들은 Linked List로 저장되며, 실행이 종료된 프로세스가 있다면 해당 PCB를 제거하고 Linked List를 최신화 함
- PCB의 구성: PCB 구조 포인터, 프로세스 상태, 프로세스 ID, 프로세스 카운터, 레지스터 정보, 메모리 관련 정보, CPU 스케줄링 정보 등
프로세스의 상태 5가지: 생성(new), 준비(ready), 실행(run), 대기(wait), 완료(exit)
- 생성: PCB 생성. 메모리에 프로그램 적재를 요청
- 준비: CPU를 사용하기 위해 기다리는 상태
- 실행: CPU 스케줄러에 의해 프로세스가 실행되는 상태. 현재 실행 중인 프로세스는 CPU의 갯수만큼 존재하며 CPU 점유 시간이 초과되면 준비 상태로 복귀
- 대기: 프로세스가 입출력 요청을 하면 입출력 작업이 종료될 때까지 기다리게 됨. (입출력은 CPU의 속도에 비하면 매~우 느린 작업. CPU를 입출력 작업 동안 마냥 기다리게 할 수 없기 때문에 대기 상태가 있음) 입출력 작업이 모두 종료되면 준비 상태로 전환
- 완료: 프로세스가 종료되는 상태. PCB가 제거되고 메모리에서 프로세스가 소멸됨.
컨텍스트 스위칭
- 프로세스 실행 중 다른 프로세스 실행을 위해 상태값을 저장하고 다른 프로세스를 시작하는 것
- 컨텍스트 스위칭이 발생하면 운영체제는 PCB에 프로세스 상태, 프로그램 카운터, 레지스터 값 등을 변경하여 최신화 함. (다시 작업할 때 처음부터 작업하지 않으려고 PCB에 현재까지의 작업내용을 적는 것이라고 생각하면 됨)
쓰레드(Thread)
- 운영체제가 작업을 수행하는 것은 프로세스. But 프로세스를 많이 생성해 사용하는 건 메모리 측면에서 많은 비용이 드는 일이다. (프로세스를 만들 때마다 메모리 영역에서 PCB, code, data, heap, stack을 새로 할당해야 하기 때문)
- 쓰레드는 프로세스 내에서 해당 프로세스의 PCB, code, data, heap을 공유하며 실행되는 작업 단위. 쓰레드는 각각 고유한 stack을 지니는데, 메모리 관점에서 하나의 프로세스를 생성(새로운 PCB, code, data, heap, stack) 하는 것보다 하나의 쓰레드를 생성(새로운 stack, TCB)하는 것이 경제적이기 때문에 쓰레드가 사용된다.
- 운영체제는 쓰레드 생성 시 새로운 쓰레드 ID와 쓰레드 관리를 위한 쓰레드 제어 블록(TCB, Thread Control Block)을 생성한다.
프로세스의 문제 발생 시 프로세스와 쓰레드: 안정성 vs 효율성
- 안정성 측면에서는 프로세스가 유리
- 효율성 측면에서는 쓰레드가 유리
안정성 측면: 각각의 프로세스는 독립적. 하나의 프로세스에 문제가 생겨도 다른 프로세스는 영향을 받지 않음.
효율성 측면: 프로세스 간의 통신에는 IPC 통신(Inter Process Communication)이 사용됨. IPC 통신은 비용이 크기 때문에 오버헤드가 크고 속도가 느림. 쓰레드는 한 프로세스 내에서 스택을 제외한 모든 자원을 공유하기 때문에 비용이 훨씬 저렴함.
'운영체제' 카테고리의 다른 글
[리눅스 운영체제] 사용자 모드와 커널 모드 (0) | 2023.02.28 |
---|---|
러프한 운영체제 기초 4편 | 가상메모리 (0) | 2022.06.05 |
러프한 운영체제 기초 3편 | 메모리 (0) | 2022.04.13 |
러프한 운영체제 기초 2편 | CPU 스케줄링과 교착 상태 (0) | 2022.03.18 |