Linux 커널 | CPU 및 프로세스 관리
프로세스란?
프로세스는 CPU에서 실행하기 위해 메모리에 로드한 프로그램이다.
프로세스 확인 명령
명령어로 실행 중인 프로세스의 확인하는 방법은 아래와 같다.
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 2.1 240344 10168 ? Ss 19:13 0:01 /usr/lib/syst
root 2 0.0 0.0 0 0 ? S 19:13 0:00 [kthreadd]
헤더 | 설명 |
---|---|
USER | 사용자 이름 |
PID | 프로세스 ID |
%CPU | 프로세스 사용률 |
%MEM | 실제 메모리에 대한 프로세스 비율 |
VSZ | 가상 메모리에 할당한 프로세스의 크기 |
RSS | 실제 메모리에 할당된 프로세스의 크기 |
TTY | 제어 터미널 |
STAT | 프로세스 상태 - D 인터럽트 불가능한 슬립 상태 (일반 IO) - R 실행 중 또는 실행 가능 상태 (실행 대기열에 있음) - S 인터럽트 가능한 슬립 상태 (이벤트 완료를 기다리고 있음) - T 작업 제어 신호 또는 추적 중이므로 정지 상태 - W 페이징 상태 (2.6.xx 커널 에서 유효하지 않음) - X 꺼진 상태 (보이지 않아야 함) - Z 사라진(좀비) 프로세스 |
START | 프로세스 시작일 |
TIME | 누적된 CPU 시간 |
COMMAND | 프로세스 실행 명령 |
메모리상의 프로세스 구조
프로세스는 메모리의 주소 공간에 다음 세그먼트(분류)별로 배치된다.
5개의 각 세그먼트에는 다음과 같은 데이터가 배치된다.
- 텍스트 세그먼트 : CPU 가 실행하는 기계어 명령
- 데이터 세그먼트 : 초기화된 static 변수 또는 전역 변수
- bss 세그먼트 : Block Stated Symbol. 초기화되지 않은 static 변수 또는 전역 변수
- 힙 세그먼트 : 프로세스 실행시 동적으로 예약 된 영역 (malloc 등)
- 스택 세그먼트 : 범위가 끝나면 사라지는 데이터 (로컬 변수, 함수 매개 변수, 메서드 등)
프로세스와 스레드의 차이
하나의 프로세스에는 하나 이상의 스레드가 있다.
프로세스와 스레드의 차이는 다음과 같다.
프로세스 | 스레드 | |
---|---|---|
설명 | 프로그램 실행 단위 | CPU 사용 단위 |
메모리 | 자식 프로세스를 위한 새로운 영역 확보 | 상위 스레드와 하위 스레드간에 공유 (스택 세그먼트 제외) |
생성 | 느리다 ( 메모리 에 새로운 영역을 확보하기 위해) |
빠르다 |
예를 들어, 그림 그리기 프로그램 이 있다고 가정하자.
- 프로세스 : 그림 그리기 프로그램을 실행
- 스레드: 실행한 그림 프로그램의 각 CPU의 처리(“마우스 조작의 대응”, “그림의 묘사” 등)
프로세스(스레드) 병렬 처리
프로세스를 CPU 로 처리하는 경우, 병렬로 처리하는 방법은 아래 4개가 존재한다.
- 멀티 CPU : 여러 CPU를 사용한다.
- 멀티 코어 : 하나의 CPU에 있는 여러 코어를 사용한다.
- 하이퍼 스레딩 : 하나의 코어에 여러 스레드를 할당한다.
- 다중 스레드 : 하나의 프로세스가 여러 스레드를 갖는다.
CPU 확인 명령어
사용하고 있는 CPU는 lscpu
(혹은 cat /proc/cpuinfo) 명령어로 확인 가능하다.
$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: AuthenticAMD
CPU family: 23
Model: 24
Model name: AMD Ryzen 5 3400G with Radeon Vega Graphics
Stepping: 1
CPU MHz: 3692.932
BogoMIPS: 7385.86
Hypervisor vendor: Microsoft
Virtualization type: full
L1d cache: 32K
L1i cache: 64K
L2 cache: 512K
L3 cache: 4096K
NUMA node0 CPU(s): 0-3
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm rep_good nopl cpuid extd_apicid pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ssbd ibpb vmmcall fsgsbase bmi1 avx2 smep bmi2 rdseed adx smap clflushopt sha_ni xsaveopt xsavec xgetbv1 xsaves xsaveerptr virt_ssbd arat
프로세스 관리란?
프로세스 관리는 언제 어느 프로세스에 CPU를 할당하는 시간을 관리하는 것이다.
하나의 프로세스가 CPU를 독점해 버리면 다른 처리를 할 수 없게 된다.
그래서, 일정 시간이 경과하면 CPU에서 처리하는 프로세스를 전환함으로써 하나의 프로세스에 의한 CPU의 독점을 막아 여러 프로세스를 병행하여 실행 가능하게 된다.
예를 들면, 1개의 CPU 로 “인터넷을 열람하는 프로세스"와 “메일을 송신하는 프로세스"를 병행해 실행 가능하게 된다.
프로세스 관리는 CPU 할당을 관리하기 위해 다음 세 가지 메커니즘을 사용한다.
- 프로세스 상태 전이 : 프로세스 상태 정의
- PCB (Process Control Block) : 상태를 포함하는 프로세스에 대한 메모리의 데이터
- 프로세스 스케줄러 : CPU에 프로세스를 할당하여 상태 변경
프로세스 상태 전이
프로세스의 라이프사이클(프로그램이 시작하고 나서 종료할 때까지)에는 아래와 같이 5개의 상태가 존재한다.
- 시작 : 초기화를 위한 상태. 실행 가능 상태로 마이그레이션
- 실행 가능 : CPU 할당을 기다리는 상태. “실행 중” 프로세스가 다른 프로세스에 인터럽트되어 중단된 경우에도 이 상태가 된다.
- 실행 중 : 프로세스에 CPU 를 할당한 (디스패치된) 상태
- 대기 : 장치 I/O (SSD 등의 데이터 읽기 / 쓰기 처리) 대기로 CPU 처리가 필요없는 경우의 상태. I/O 처리가 끝나면 “실행 가능” 상태로 이동한다.
- 종료 : 프로세스의 처리가 완료 혹은 중지한 경우에 이 상태가 된다.
PCB (Process Control Block)
상태를 포함하는 프로세스에 대한 정보는 메모리의 커널 스택에 다음 PCB 넣어 관리한다.
각 항목의 의미는 다음과 같다. 그 밖에도 여러가지 있다.
- Process ID : 프로세스를 고유하게 식별하는 번호입니다. (PID)
- State : 프로세스의 상태 천이 에서 현재 어느 상태인지를 나타냅니다.
- Pointer : 부모 프로세스 포인터
- Priority : 프로세스 우선 순위
- Program Counter: 다음에 실행할 명령의 포인터
- CPU registers : 실행중인 상태의 프로세스 레지스터 값 (?)
- I/O Information : 프로세스에 할당된 I/O 장치 목록
- Accounting information : 프로세스를 실행하는 데 사용되는 CPU 의 양, 시간 제한 및 실행 ID
CPU 스케줄러 (단기 스케줄러)
CPU 스케줄러는 실행 가능 상태의 프로세스에서 CPU를 할당하는 프로세스를 결정한다.
CPU 스케줄러가 다음에 CPU를 할당하는 프로세스를 결정하면, 인터럽트에 의해 디스패처가 “선점"과 “디스패치"를 실시하는 것으로 프로세스를 전환한다.
- 선점 : 실행중인 프로세스의 상태를 실행 중에서 실행 가능으로 변경
- 디스패치 : 대기 중인 프로세스의 상태를 ‘실행 가능’에서 ‘실행 중’으로 변경
디스패처에 의해 처리를 중단한 프로세스는 PCB에 재개 지점을 나타내는 프로그램 카운터나 레지스터의 값을 보존한다. 이 중단 처리나 재개되는 처리를 컨텍스트 스위치 라고 한다.
프로세스 스케줄러가 CPU의 할당을 결정할 때 이용하는 스케줄링 알고리즘에는 주로 아래 4개가 존재한다.
- First Come First Serve (FCFS)
- Shortest Job Next (SJN)
- Priority Based Scheduling
- Round Robin Scheduling
First Come First Serve (FCFS)
FCFS에는 다음과 같은 특징이 있습.
- 선착순으로 프로세스 실행
- FIFO (First In First Out) 큐에서 구현
- non-preemptive(인터럽트 불가능)
- 평균 대기 시간이 길다.
https://www.tutorialspoint.com/operating_system/os_process_scheduling_algorithms.htm
평균 대기 시간: (0+4+6+13) / 4 = 5.75
Shortest Job Next (SJN)
SJN에는 다음과 같은 특징이 있다.
- 처리 시간이 짧은 프로세스에서 CPU 할당
- 평균 대기 시간을 최소화하는 알고리즘
- non-preemptive(인터럽트 불가능)
- CPU 처리 시간을 미리 알고 (또는 계산)해야 한다.
Process | Arrival Time | Execution Time | Service Time |
---|---|---|---|
P0 | 0 | 5 | 0 |
P1 | 1 | 3 | 5 |
P2 | 2 | 8 | 14 |
P3 | 3 | 6 | 8 |
평균 대기 시간: (0 + 4 + 12 + 5)/4 = 21 / 4 = 5.25
Priority Based Scheduling
Priority Based Scheduling에는 다음과 같은 특징이 있다.
- 우선순위가 높은 프로세스에서 실행
- 동일한 우선순위의 프로세스는 선착순이다.
- 우선 순위는 메모리 요구 사항, 시간 요구 사항 등에 따라 결정된다.
프로세스의 우선 순위는 다음 명령 결과의 PRI 열에서 확인할 수 있다. (낮은 편이 우선도가 높음)
프로세스 우선 순위 확인
$ ps alx
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
1 0 2 0 20 0 0 0 - S ? 0 :01 [kthreadd]
1 0 4 2 0 -20 0 0 - I< ? 0 :00 [kworker/0 :0H]
PRI는 NI(nice 값)를 기반으로 결정하므로, nice 명령으로 프로세스 우선 순위를 변경할 수 있다.
Process | Arrival Time | Execution Time | Service Time |
---|---|---|---|
P0 | 0 | 5 | 1 |
P1 | 1 | 3 | 2 |
P2 | 2 | 8 | 1 |
P3 | 3 | 6 | 3 |
평균 대기 시간: (0 + 10 + 12 + 2)/4 = 24 / 4 = 6
Round Robin Scheduling
Round Robin Scheduling에는 다음과 같은 특징이 있다.
- 각 프로세스에는 퀀텀(CPU 를 할당하는 고정 시간)이 있다.
- preemptive(인터럽트 발생) 때문에 프로세스가 병렬로 작동 가능
- 퀀텀 기간이 끝나면 인터럽트가 발생하고 다음 프로세스로 진행된다.
- 퀀텀이 3이라면, 3경과마다 프로세스가 전환된다.
평균 대기 시간: (9+2+12+11) / 4 = 8.5