[OS] Process์ Thread
๐งฉ Process
์ด์์ฒด์ ๋ ์คํ ์ค์ธ ํ๋ก๊ทธ๋จ์ธ ํ๋ก์ธ์ค๋ฅผ ํตํด ํ๋์จ์ด ์์์ ๊ด๋ฆฌํฉ๋๋ค. ์ฌ๋ฌ ํ๋ก์ธ์ค๊ฐ ๋์์ ๊ตฌ๋๋๋ ํ๊ฒฝ์์ ๊ฐ ํ๋ก์ธ์ค๋ CPU์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ ์ ์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ๋์ํ๋ฉฐ, ์ด์์ฒด์ ๋ ์ด๋ฅผ ์ํ ๊ฒฉ๋ฆฌ๋ ์คํ ํ๊ฒฝ์ ๋ณด์ฅํฉ๋๋ค. ํ๋ก์ธ์ค๋ ๋จ์ํ ์คํ ์ค์ธ ์ํ๋ฅผ ๋์ด, ์์คํ ์์์ ์์ ํ๊ฒ ๊ณต์ ํ๊ธฐ ์ํ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ฒฉ๋ฆฌ ๋จ์์ ๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๊ฒฉ๋ฆฌ์ ์ฃผ์ ๊ณต๊ฐ
ํ๋ก์ธ์ค ์์ฑ ์ ์ด์์ฒด์ ๋ ํด๋น ํ๋ก์ธ์ค ์ ์ฉ์ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ ํ ๋นํฉ๋๋ค. ์ด ๊ณต๊ฐ์ ์คํ ์ฝ๋๊ฐ ๋ด๊ธด Text, ์ ์ญ ๋ฐ ์ ์ ๋ณ์๊ฐ ์์นํ Data, ๋์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ์ํ Heap, ํจ์ ํธ์ถ๊ณผ ์ง์ญ ๋ณ์๋ฅผ ์ฒ๋ฆฌํ๋ Stack์ผ๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
์ด ์ค๊ณ์ ๋ชฉ์ ์ ํ๋ก์ธ์ค ๊ฐ์ ๋ ๋ฆฝ์ฑ์ ํ๋ณดํ๋ ๋ฐ ์์ต๋๋ค. ํ๋ก์ธ์ค๋ ๋ค๋ฅธ ํ๋ก์ธ์ค์ ์ฃผ์ ๊ณต๊ฐ์ ์ง์ ์ ๊ทผํ ์ ์์ผ๋ฉฐ, ํ์ฉ๋์ง ์์ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์นจ๋ฒํ ๊ฒฝ์ฐ ํ๋์จ์ด(MMU)์ ์ด์์ฒด์ ๊ฐ ์ด๋ฅผ ์ฐจ๋จํฉ๋๋ค. ์ด๋ ๋ฐ์ํ๋ Segmentation Fault๋ ํด๋น ํ๋ก์ธ์ค๋ฅผ ์ฆ์ ์ข ๋ฃ์์ผ ์์คํ ์ ์ฒด์ ์์ ์ฑ์ ์ ์งํ๋ ์ญํ ์ ํฉ๋๋ค.
PCB์ ์ ๋ณด์ ์ญํ
์ด์์ฒด์ ๋ ์๋ง์ ํ๋ก์ธ์ค๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ๊ฐ ํ๋ก์ธ์ค์ ์ํ ์ ๋ณด๋ฅผ ๊ธฐ๋กํ PCB(Process Control Block)๋ฅผ ์ปค๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์์ฑํฉ๋๋ค. PCB๋ ํ๋ก์ธ์ค๊ฐ ์ค๋จ๋์๋ค๊ฐ ๋ค์ ์คํ๋ ๋ ์ด์ ์ ์คํ ์ํ๋ฅผ ์๋ฒฝํ๊ฒ ๋ณต์ํ๊ธฐ ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ดํฉ๋๋ค.
PCB์๋ ํ๋ก์ธ์ค ์๋ณ์ ์ํ PID, ํ์ฌ ์คํ ์ํ(New, Ready, Running, Waiting, Terminated), ๋ค์์ ์คํํ ๋ช ๋ น์ด ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ Program Counter, ๊ทธ๋ฆฌ๊ณ CPU ๋ ์ง์คํฐ ๊ฐ๊ณผ ๋ฉ๋ชจ๋ฆฌ ๋งคํ ์ ๋ณด ๋ฑ์ด ํฌํจ๋ฉ๋๋ค.
ํ๋ก์ธ์ค์ ์๋ช ์ฃผ๊ธฐ์ fork()
์ ๋์ค ๊ณ์ด ์์คํ ์์๋
fork()์์คํ ์ฝ์ ์ฌ์ฉํ์ฌ ๋ถ๋ชจ ํ๋ก์ธ์ค๋ฅผ ๋ณต์ ํด ์์ ํ๋ก์ธ์ค๋ฅผ ์์ฑํฉ๋๋ค. ์์ ํ๋ก์ธ์ค๋ ๋ถ๋ชจ์ PCB ์ ๋ณด์ ๋ฉ๋ชจ๋ฆฌ ์ํ๋ฅผ ์์๋ฐ์ ๋ ๋ฆฝ์ ์ธ ์คํ ํ๋ฆ์ ๊ฐ๊ฒ ๋ฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid;
printf("fork() ํธ์ถ ์ . (๋ถ๋ชจ PID: %d)\n", getpid());
// ์๋ก์ด ํ๋ก์ธ์ค ์์ฑ (๋ถ๋ชจ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ๋ณต์ )
pid = fork();
if (pid < 0) {
// fork ์คํจ
fprintf(stderr, "fork failed\n");
return 1;
} else if (pid == 0) {
// ์์ ํ๋ก์ธ์ค ์ฝ๋ ์์ญ
// ์์์๊ฒ fork์ ๋ฐํ๊ฐ์ 0์
๋๋ค.
printf("์ ๋ ์์ ํ๋ก์ธ์ค์
๋๋ค. (PID: %d, ๋ถ๋ชจ PID: %d)\n", getpid(), getppid());
} else {
// ๋ถ๋ชจ ํ๋ก์ธ์ค ์ฝ๋ ์์ญ
// ๋ถ๋ชจ์๊ฒ fork์ ๋ฐํ๊ฐ์ ์์ฑ๋ ์์์ PID์
๋๋ค.
printf("์ ๋ ๋ถ๋ชจ ํ๋ก์ธ์ค์
๋๋ค. (PID: %d, ์์ PID: %d)\n", getpid(), pid);
}
// ๋ถ๋ชจ์ ์์ ๋ชจ๋ ์ด ์ฝ๋๋ฅผ ์คํํ์ง๋ง, ๊ฐ์์ ์ฃผ์ ๊ณต๊ฐ์์ ์คํ๋ฉ๋๋ค.
printf("ํ๋ก์ธ์ค ์ข
๋ฃ. (PID: %d)\n", getpid());
return 0;
}
ํ๋ก์ธ์ค ๊ต์ฒด ๊ณผ์
CPU ์ฝ์ด๋ ํ ๋ฒ์ ํ๋์ ๋ช ๋ น์ด๋ง ์ฒ๋ฆฌํ ์ ์์ง๋ง, ์ด์์ฒด์ ๋ ํ๋ก์ธ์ค๋ฅผ ๋งค์ฐ ์งง์ ์๊ฐ ๋จ์๋ก ๊ต์ฒดํ๋ ์ปจํ ์คํธ ์ค์์นญ์ ํตํด ๋ฉํฐํ์คํน์ ๊ตฌํํฉ๋๋ค.
์ด ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ์งํ๋ฉ๋๋ค.
- ์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ํ์ฌ ์ ์ด๊ถ์ด ์ปค๋ ๋ชจ๋๋ก ์ ํ๋ฉ๋๋ค.
- ํ์ฌ ์คํ ์ค์ธ ํ๋ก์ธ์ค์ ๋ ์ง์คํฐ ์ํ๋ฅผ ํด๋น PCB์ ์ ์ฅํฉ๋๋ค.
- ์ค์ผ์ค๋ฌ๊ฐ ๋ค์์ ์คํํ ํ๋ก์ธ์ค๋ฅผ ์ ํํฉ๋๋ค.
- ์๋ก ์ ํ๋ ํ๋ก์ธ์ค์ PCB์์ ๋ ์ง์คํฐ ์ํ๋ฅผ ๋ณต์ํฉ๋๋ค.
- ์ ์ ๋ชจ๋๋ก ์ ํํ์ฌ ํ๋ก์ธ์ค ์คํ์ ์ฌ๊ฐํฉ๋๋ค.
์ปจํ ์คํธ ์ค์์นญ์ ๋ฉํฐํ์คํน์ ์ํ ํ์์ ์ธ ์ ์ฐจ์ด์ง๋ง, CPU๊ฐ ์ค์ ์ฐ์ฐ์ ์ํํ์ง ๋ชปํ๋ ์์ ์ค๋ฒํค๋ ๋น์ฉ์ด๊ธฐ๋ ํฉ๋๋ค.
๐งฉ Thread
์ค๋ ๋๋ ํ๋ก์ธ์ค ๋ด์์ ์คํ๋๋ ํ๋ฆ์ ๋จ์์ ๋๋ค. ํ๋์ ํ๋ก์ธ์ค ์์์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์์ ์ ์ํํ๋ฉฐ, ํ๋ก์ธ์ค์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ ์ค ํ ์์ญ๊ณผ ๋ฐ์ดํฐ ์์ญ์ ๊ณต์ ํฉ๋๋ค. ์ด๋ฌํ ์์ ๊ณต์ ๋๋ถ์ ์ค๋ ๋๋ ํ๋ก์ธ์ค๋ณด๋ค ์์ฑ ๋น์ฉ์ด ์ ๋ ดํ๋ฉฐ, ๋ณ๋์ ํต์ ๊ณผ์ ์์ด ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ์ฝ๊ณ ์ฐ๋ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ตํํ ์ ์์ต๋๋ค.
์์ ๊ณต์ ์ ์คํ ํ๋ฆ
์ค๋ ๋์ ๋ณธ์ง์ ์คํ ํ๋ฆ์ ๋ถ๋ฆฌ์ ์์ต๋๋ค. ๋ชจ๋ ์ค๋ ๋๋ ์์๋ ํ๋ก์ธ์ค์ ์ฃผ์ ๊ณต๊ฐ์ ๊ณต์ ํ๋, ๊ฐ์๊ฐ ์ฝ๋๋ฅผ ์คํํ ์์น์ ์ฐ์ฐ ์ค์ธ ์์ ๊ฐ์ ๋ ๋ฆฝ์ ์ผ๋ก ๊ด๋ฆฌํด์ผ ํฉ๋๋ค.
์ค๋ ๋ ๊ฐ์ ๊ณต์ ๋๋ ์์๊ณผ ๊ฒฉ๋ฆฌ๋๋ ์์ญ์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ๋ถ๋ฉ๋๋ค.
- ๊ณต์ ์์ญ: ์ฝ๋(Text), ์ ์ญ ๋ณ์(Data), ๋์ ํ ๋น ๋ฉ๋ชจ๋ฆฌ(Heap), ์ด๋ฆฐ ํ์ผ ํธ๋ค ๋ฑ ํ๋ก์ธ์ค์ ๊ณต์ฉ ์์.
- ๊ฒฉ๋ฆฌ ์์ญ: ๊ฐ ์ค๋ ๋๋ง์ ๋ ๋ฆฝ์ ์ธ ์คํ๊ณผ ๋ ์ง์คํฐ ์งํฉ(PC ๋ฑ).
์ด๋ฌํ ๊ตฌ์กฐ ๋๋ถ์ ์ค๋ ๋ ๊ฐ์ ์ปจํ ์คํธ ์ค์์นญ์ ํ๋ก์ธ์ค ์ ํ๋ณด๋ค ๋น์ฉ์ด ์ ๊ฒ ๋ญ๋๋ค. ํ์ด์ง ํ ์ด๋ธ์ ๊ต์ฒดํ ํ์ ์์ด CPU ๋ ์ง์คํฐ ๊ฐ๋ง ๋ณ๊ฒฝํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
TCB์ ์ ์ฉ ์คํ ํ ๋น
์ด์์ฒด์ ์ค์ผ์ค๋ง์ ์ต์ ๋จ์๋ ์ค๋ ๋์ ๋๋ค. ์ปค๋์ ์ค๋ ๋ ๊ด๋ฆฌ๋ฅผ ์ํด TCB(Thread Control Block)๋ผ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ ์งํ๋ฉฐ, ์ฌ๊ธฐ์๋ ์ค๋ ๋์ ์คํ ์ํ, CPU ๋ ์ง์คํฐ ๊ฐ, ์คํ ํฌ์ธํฐ ๋ฑ์ด ๊ธฐ๋ก๋ฉ๋๋ค.
์ค๋ ๋๊ฐ ์์ฑ๋ ๋ ์ด์์ฒด์ ๋ ํด๋น ์ค๋ ๋ ์ ์ฉ ์คํ์ ํ๋ก์ธ์ค์ ์ฃผ์ ๊ณต๊ฐ ๋ด์ ํ ๋นํฉ๋๋ค. ์ด ๊ณต๊ฐ์ ํจ์ ํธ์ถ ์ ๋ฐ์ํ๋ ์ง์ญ ๋ณ์์ ๋ณต๊ท ์ฃผ์๋ฅผ ์ ์ฅํ๋ฉฐ, ์ค๋ ๋ ๊ฐ์ ์คํ ํ๋ฆ์ด ์์ด์ง ์๋๋ก ๋ณด์ฅํ๋ ์ญํ ์ ํฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// ๋ชจ๋ ์ค๋ ๋๊ฐ ๊ณต์ ํ๋ ์ ์ญ ๋ณ์ (Data ์์ญ)
int shared_counter = 0;
// ์ค๋ ๋๊ฐ ์คํํ ํจ์
void *thread_function(void *arg) {
char *thread_name = (char *)arg;
int i;
// ๊ฐ ์ค๋ ๋๋ ์์ ๋ง์ ์คํ์ ์ง์ญ ๋ณ์ i๋ฅผ ๊ฐ์ง๋๋ค.
for (i = 0; i < 1000000; i++) {
// ๊ณต์ ๋ณ์์ ๋์ ์ ๊ทผ (๊ฒฝ์ ์ํ ๋ฐ์ ๊ฐ๋ฅ)
shared_counter++;
}
printf("%s ์์
์๋ฃ.\n", thread_name);
return NULL;
}
int main() {
pthread_t thread1, thread2;
// ๋ ๊ฐ์ ์ค๋ ๋ ์์ฑ
// ๊ฐ ์ค๋ ๋๋ thread_function์ ์คํํ๋ฉฐ, ๋์ผํ shared_counter๋ฅผ ๊ณต์ ํฉ๋๋ค.
pthread_create(&thread1, NULL, thread_function, "Thread 1");
pthread_create(&thread2, NULL, thread_function, "Thread 2");
// ์ค๋ ๋๊ฐ ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐ (๋ฉ์ธ ์ค๋ ๋ ๋ธ๋กํน)
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// ๊ฒฐ๊ณผ ์ถ๋ ฅ (๋๊ธฐํ๊ฐ ์๋ค๋ฉด 2000000์ด ์๋ ์ ์์)
printf("์ต์ข
์นด์ดํฐ ๊ฐ: %d\n", shared_counter);
return 0;
}
๋ฐ์ดํฐ ์ถฉ๋๊ณผ ๋๊ธฐํ
์์์ ๊ณต์ ํ๋ค๋ ํน์ง์ ๋ฐ์ดํฐ ์ ํฉ์ฑ ๋ฌธ์ ๋ก ์ด์ด์ง๋๋ค. ์ฌ๋ฌ ์ค๋ ๋๊ฐ ํ๋์ ์์์ ๋์์ ์ ๊ทผํ์ฌ ๊ฐ์ ์์ ํ ๋ ๊ฒฝ์ ์ํ(Race Condition)๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ณ ๋ถํ ์์คํ ์์ ํ ์ค๋ ๋๊ฐ ๊ณต์ ๋ณ์๋ฅผ ์์ ํ๋ ๋์ค์ ์ปจํ ์คํธ ์ค์์นญ์ด ์ผ์ด๋ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ํด๋น ๊ฐ์ ๋ณ๊ฒฝํด๋ฒ๋ฆฌ๋ฉด ๋ ผ๋ฆฌ์ ์ธ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋ฐ๋ผ์ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ์ ์ ์งํ๊ธฐ ์ํ ๋๊ธฐํ ์ฒ๋ฆฌ๊ฐ ํ์์ ์ ๋๋ค.
์ ๊ธ ์ฅ์น์ ๋ณ๋ ฌ์ฑ ์ ํ
์ค๋ ๋ ์์ ์ฑ(Thread Safety)์ ํ๋ณดํ๊ธฐ ์ํด ๋ฎคํ ์ค๋ ์ธ๋งํฌ์ด ๊ฐ์ ์ ๊ธ ์ฅ์น๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณ๋ ฌ์ฑ์ด ์ ํ๋ ์ ์์ต๋๋ค. ํน์ ์์์ ์ฌ์ฉํ๊ธฐ ์ํด ์ค๋ ๋๋ค์ด ๋๊ธฐ ์ํ์ ๋จธ๋ฌผ๊ฒ ๋๋ฉด์ ์ฒ๋ฆฌ๋์ด ๊ธ๊ฐํ๋ ์ ๊ธ ๊ฒฝํฉ(Lock Contention) ํ์์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ฒฐ๊ตญ ํจ์จ์ ์ธ ๋ฉํฐ์ค๋ ๋ฉ์ ํต์ฌ์ ๋จ์ํ ์ค๋ ๋ ๊ฐ์๋ฅผ ๋๋ฆฌ๋ ๊ฒ์ด ์๋๋ผ, ๊ณต์ ์์์ ์ต์ํํ๊ณ ๋๊ธฐํ ๋น์ฉ์ ์ค์ด๋ ์ค๊ณ์ ์์ต๋๋ค.
Cache Pollution
์ปจํ ์คํธ ์ค์์นญ์ ๋น์ฉ์ ๋ ์ง์คํฐ ์ ์ฅ๊ณผ ๋ณต์๋ฟ๋ง ์๋๋ผ ์บ์ ์ค์ผ์์๋ ๋ฐ์ํฉ๋๋ค. ํ๋ก์ธ์ค๊ฐ ๊ต์ฒด๋ ์งํ ํ๋์จ์ด ์บ์์ ํจ์จ์ด ๊ธ๊ฒฉํ ๋จ์ด์ง๋ ํ์์ ์๋ฏธํฉ๋๋ค.
์บ์ ๋ฐ์ดํฐ ๋ฌดํจํ
CPU๋ ๋จ์ ์๋ ํ๊ณ๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด L1, L2, L3 ์บ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ค. ํ๋ก์ธ์ค ์คํ ์ค์๋ ์ฐธ์กฐ ๊ตญ์์ฑ ์๋ฆฌ์ ๋ฐ๋ผ ์์ฃผ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ์ ๋ช ๋ น์ด๊ฐ ์บ์์ ์ ์ฌ๋ฉ๋๋ค.
ํ์ง๋ง ์ปจํ ์คํธ ์ค์์นญ์ด ์ผ์ด๋๋ฉด ์๋ก์ด ํ๋ก์ธ์ค๊ฐ ๊ธฐ์กด ํ๋ก์ธ์ค์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ด๋ด๊ณ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ์ฑ์ฐ๊ธฐ ์์ํฉ๋๋ค. ์ด ๊ณผ์ ์์ ๊ธฐ์กด ํ๋ก์ธ์ค๊ฐ ๊ตฌ์ถํด๋ ์ํน ์ ์ด ์ ์ค๋ฉ๋๋ค. ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฒ์ผ๋ก ๋ฐ์ดํฐ ๋ณต์ฌ ๋น์ฉ์ ์ค์ผ ์ ์์ง๋ง, ๋ฌผ๋ฆฌ์ ์ธ ์บ์ ์ ์ ์ํ๊น์ง ๋ณด์กดํ ์๋ ์์ต๋๋ค.
๊ต์ฒด ์งํ์ ์๋ ํ๋ฝ
์บ์ ์ค์ผ์ ํ๋ก์ธ์ค ์ฌ์คํ ์ ์บ์ ๋ฏธ์ค์ ์ฆ๊ฐ๋ก ์ด์ด์ง๋๋ค. CPU๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ธฐ ์ํด ์๋์ ์ผ๋ก ๋๋ฆฐ ๋จ์ ์ ๊ทผํด์ผ ํ๋ฏ๋ก ์ฐ์ฐ ์๋๊ฐ ์ ํ๋ฉ๋๋ค.
ํนํ ๊ณ ๋ถํ ํ๊ฒฝ์์๋ ๋ค์๊ณผ ๊ฐ์ ์์ธ์ด ์ฑ๋ฅ์ ์ํฅ์ ์ค๋๋ค.
- TLB Flush: ์ฃผ์ ๋ณํ ์ ๋ณด๋ฅผ ๋ด์ TLB๊ฐ ์ค์์นญ ์์ ์ ๋ฌดํจํ๋๊ฑฐ๋ ๊ต์ฒด๋์ด ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจ์จ์ด ๋จ์ด์ง๋๋ค.
- ์ํ ๋ณต๊ตฌ ๋น์ฉ: ์บ์ ํํธ์จ์ด ์ ์ ๊ถค๋์ ์ค๋ฅด๊ธฐ๊น์ง ๊ฑธ๋ฆฌ๋ ์ฝ๋ ์บ์ ๊ตฌ๊ฐ์์ ์์คํ ๋ ์ดํด์๊ฐ ๋ฐ์ํฉ๋๋ค.
๊ณผ๋ํ ์ค๋ ๋ ์์ฑ์ด ์ํํ ์ด์
CPU ์ฝ์ด ์๋ณด๋ค ์ค๋ ๋๋ฅผ ๊ณผํ๊ฒ ์์ฑํ๋ฉด ์ปจํ ์คํธ ์ค์์นญ ๋น๋๊ฐ ๋์์ ธ ์บ์ ์ค์ผ์ด ์์ํ๋ฉ๋๋ค. ์ด๋ ์ค์ ์ฐ์ฐ๋ณด๋ค ์บ์๋ฅผ ๊ต์ฒดํ๋ ์์ ์ ์์์ด ๋ญ๋น๋๋ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ํฉ๋๋ค.
Copy-on-Write
fork() ์์คํ
์ฝ ํธ์ถ ์ ์ด์์ฒด์ ๊ฐ ๋ถ๋ชจ ํ๋ก์ธ์ค์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ์ ์ฒด๋ฅผ ์ฆ์ ๋ณต์ฌํ๋ฉด ์๋นํ ์์๊ณผ ์๊ฐ์ด ์๋ชจ๋ฉ๋๋ค. ์ด์์ฒด์ ๋ ์ด๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฐ๊ธฐ ์ ๋ณต์ฌ(์ดํ COW)๋ผ๋ ์ง์ฐ ๋ณต์ฌ ์ ๋ต์ ์ฌ์ฉํฉ๋๋ค.
fork์ ์ง์ฐ ๋ณต์ฌ ์ ๋ต
COW๋ ์ค์ ์์ ์ด ๋ฐ์ํ๊ธฐ ์ ๊น์ง ๋ฉ๋ชจ๋ฆฌ ๋ณต์ฌ๋ฅผ ๋ฏธ๋ฃจ๋ ๋ฐฉ์์
๋๋ค. fork()๊ฐ ์คํ๋๋ฉด ์ด์์ฒด์ ๋ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ณต์ฌํ์ง ์๊ณ ๋ถ๋ชจ ํ๋ก์ธ์ค์ ํ์ด์ง ํ
์ด๋ธ๋ง ๋ณต์ ํฉ๋๋ค.
์ด ์์ ์ ๋ถ๋ชจ์ ์์ ํ๋ก์ธ์ค๋ ๋์ผํ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ํ์ด์ง๋ฅผ ๊ณต์ ํ๊ฒ ๋ฉ๋๋ค. ์ด ๋ฐฉ์ ๋๋ถ์ ํ๋ก์ธ์ค์ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ์ ๊ด๊ณ์์ด ์์ฑ ์์ ์ด ๋น ๋ฅด๊ฒ ์๋ฃ๋ฉ๋๋ค.
๋ฐ์ดํฐ ์์ ๊ณผ ์ค์ ๋ณต์ฌ
ํ๋ก์ธ์ค ๊ฐ ๊ฒฉ๋ฆฌ๋ฅผ ์ ์งํ๊ธฐ ์ํด ์ด์์ฒด์ ๋ ๊ณต์ ์ค์ธ ๋ชจ๋ ํ์ด์ง๋ฅผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ์ค์ ํฉ๋๋ค. ์ดํ ํน์ ํ๋ก์ธ์ค๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ค๊ณ ์๋ํ ๋ ์ค์ ๋ณต์ฌ๊ฐ ์ผ์ด๋ฉ๋๋ค.
- ํ์ด์ง ํดํธ ๋ฐ์: ์ฝ๊ธฐ ์ ์ฉ ํ์ด์ง์ ์ฐ๊ธฐ๋ฅผ ์๋ํ๋ฉด ํ๋์จ์ด๊ฐ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค.
- ์ปค๋ ๊ฐ์ : ์ด์์ฒด์ ๊ฐ ํด๋น ํ์ด์ง์ COW ์ค์ ์ ํ์ธํฉ๋๋ค.
- ์ง์ฐ๋ ๋ณต์ฌ: ์ฐ๊ธฐ๋ฅผ ์๋ํ ์์ ์ ํด๋น ํ์ด์ง๋ง ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์ ์๋ก์ด ์์ญ์ผ๋ก ๋ณต์ฌํฉ๋๋ค.
- ํ์ด์ง ํ ์ด๋ธ ์ ๋ฐ์ดํธ: ๋ณต์ฌ๋ ์๋ก์ด ๋ฌผ๋ฆฌ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํ ์ด๋ธ์ ์์ ํ๊ณ ๊ถํ์ ์ฝ๊ธฐ/์ฐ๊ธฐ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
Redis์ ์ค๋จ ์๋ ์ค๋ ์ท
Redis๋
BGSAVE๋ช ๋ น ์fork()๋ฅผ ํธ์ถํ์ฌ ์์ ํ๋ก์ธ์ค๋ฅผ ์์ฑํฉ๋๋ค. COW๋ฅผ ํ์ฉํ๋ฉด ์๋น์ค ์ค๋จ ์์ด ์์ ํ๋ก์ธ์ค๊ฐ ์์ฑ ์์ ์ ๋ฉ๋ชจ๋ฆฌ ์ํ๋ฅผ ์ค๋ ์ท์ผ๋ก ์ ์งํ๋ฉฐ ๋์คํฌ์ ์ ์ฅํ ์ ์์ต๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
// ์ด๊ธฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง ๋ณ์
int data = 100;
pid_t pid;
printf("fork() ์ : data = %d, ์ฃผ์ = %p\n", data, &data);
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork error\n");
return 1;
} else if (pid == 0) {
// [์์ ํ๋ก์ธ์ค]
// ์ด ์์ ๊น์ง๋ COW์ ์ํด ๋ถ๋ชจ์ ๋์ผํ ๋ฌผ๋ฆฌ ํ์ด์ง๋ฅผ ๊ณต์ ํฉ๋๋ค.
printf("[์์] ์ฐ๊ธฐ ์ : data = %d, ์ฃผ์ = %p (๋ถ๋ชจ์ ๊ฐ์ ์ฃผ์ ๋์ผ)\n", data, &data);
// ์์ ํ๋ก์ธ์ค๊ฐ ๊ฐ์ ์์ ํ๋ ์๊ฐ, ํ์ด์ง ๋ณต์ฌ(COW)๊ฐ ๋ฐ์ํฉ๋๋ค.
data = 200;
printf("[์์] ์ฐ๊ธฐ ํ: data = %d, ์ฃผ์ = %p (๊ฐ ๋ณ๊ฒฝ๋จ, ์๋ก์ด ๋ฌผ๋ฆฌ ํ์ด์ง)\n", data, &data);
} else {
// [๋ถ๋ชจ ํ๋ก์ธ์ค]
// ์์์ด ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐํ์ฌ ์ถ๋ ฅ์ด ์์ด์ง ์๊ฒ ํฉ๋๋ค.
wait(NULL);
// ๋ถ๋ชจ์ ๋ฐ์ดํฐ๋ ์์์ ์์ ์ ์ํฅ์ ๋ฐ์ง ์์ต๋๋ค (๊ฒฉ๋ฆฌ ๋ณด์ฅ).
printf("[๋ถ๋ชจ] ์์ ์ข
๋ฃ ํ: data = %d, ์ฃผ์ = %p (๊ฐ ์ ์ง๋จ)\n", data, &data);
}
return 0;
}
M:N Scheduling
์ด์์ฒด์ ๊ฐ ๊ด๋ฆฌํ๋ ์ปค๋ ์ค๋ ๋๋ ์์ฑ ์ ์ฝ 1MB์ ์คํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ ๋น๋๋ฉฐ, ์ปจํ ์คํธ ์ค์์นญ๋ง๋ค ์ปค๋ ๋ชจ๋ ์ง์ ์ด ํ์ํ์ฌ ๋น์ฉ์ด ๋์ต๋๋ค. ๋๊ท๋ชจ ๋์ ์ ์์ ์ฒ๋ฆฌํ๋ ์์คํ ์์ ์ ์์๋ง๋ค ์ปค๋ ์ค๋ ๋๋ฅผ ํ ๋นํ๋ ๋ฐฉ์์ ์์ ๋ถ์กฑ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ ์ ๋ ๋ฒจ ์ค๋ ๋์ ์ปค๋ ์ค๋ ๋๋ฅผ ํจ์จ์ ์ผ๋ก ๋งคํํ๋ M:N ์ค์ผ์ค๋ง์ด ๋์ ๋์์ต๋๋ค.
์ค๋ ๋ ๋งคํ ๋ฐฉ์
์ค๋ ๋ ๋ชจ๋ธ์ ๊ธฐ์ ์ ์๊ตฌ์ ๋ฐ๋ผ ์ธ ๊ฐ์ง ๋ฐฉ์์ผ๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
- 1:1 ๋ชจ๋ธ: ์ ์ ์ค๋ ๋ ํ๋๊ฐ ์ปค๋ ์ค๋ ๋ ํ๋์ ์ง์ ๋งคํ๋๋ ๊ตฌ์กฐ์ ๋๋ค. ์๋ฐ์ ์ ํต์ ์ธ ๋ฒ์ ์ด๋ C++์์ ์ฌ์ฉํ๋ฉฐ, ๋ฉํฐ์ฝ์ด ํ์ฉ์ ์ ๋ฆฌํ์ง๋ง ์์ฑ๊ณผ ์ค์์นญ ๋น์ฉ์ด ํฝ๋๋ค.
- N:1 ๋ชจ๋ธ: ์ฌ๋ฌ ์ ์ ์ค๋ ๋๊ฐ ํ๋์ ์ปค๋ ์ค๋ ๋ ์์์ ๋์ํฉ๋๋ค. ์ปจํ ์คํธ ์ค์์นญ์ ๋น ๋ฅด์ง๋ง, ํ๋์ ์ค๋ ๋์์ ๋ธ๋กํน ์์คํ ์ฝ์ด ๋ฐ์ํ๋ฉด ํด๋น ์ปค๋ ์ค๋ ๋์ ์ํ ๋ชจ๋ ์ ์ ์ค๋ ๋๊ฐ ์ค๋จ๋๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
- M:N ๋ชจ๋ธ: ๋ค์์ ์ ์ ์ค๋ ๋๋ฅผ ์๋์ ์ผ๋ก ์ ์ ์์ ์ปค๋ ์ค๋ ๋์ ๋์ ์ผ๋ก ํ ๋นํฉ๋๋ค. Go ์ธ์ด์ ๊ณ ๋ฃจํด์ด๋ ์๋ฐ 21์ ๊ฐ์ ์ค๋ ๋๊ฐ ์ด ๋ฐฉ์์ ๋ฐ๋ฆ ๋๋ค.
M:N ๋ชจ๋ธ์์๋ ์ด์์ฒด์ ๊ฐ ์๋ ์ธ์ด์ ๋ฐํ์ ์ค์ผ์ค๋ฌ๊ฐ ์ ์ ์ค๋ ๋๋ฅผ ๊ด๋ฆฌํ๋ฉฐ, ์ด๋ค ์ปค๋ ์ค๋ ๋์ ์์ ์ ์ฌ๋ฆด์ง ๊ฒฐ์ ํฉ๋๋ค.
๋ฐํ์ ์์ ๋ถ๋ฐฐ
M:N ๋ชจ๋ธ์ ํต์ฌ ์๊ณ ๋ฆฌ์ฆ ์ค ํ๋๋ ์ํฌ ์คํธ๋ง(Work Stealing)์ ๋๋ค. ํน์ ์ปค๋ ์ค๋ ๋๊ฐ ์์ ์๊ฒ ํ ๋น๋ ์์ ์ ๋ชจ๋ ์ฒ๋ฆฌํ๋ฉด ๋ค๋ฅธ ์ค๋ ๋์ ์์ ํ์์ ํ์คํฌ๋ฅผ ๊ฐ์ ธ์ ์ฒ๋ฆฌํจ์ผ๋ก์จ CPU ๊ฐ๋๋ฅ ์ ๊ทน๋ํํฉ๋๋ค.
์ด๋ฌํ ๋ฐฉ์์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ๋ ๋์ต๋๋ค. ๊ณ ๋ฃจํด์ ์ KB์ ๋ฉ๋ชจ๋ฆฌ๋ก ์์ํ์ฌ ํ์์ ๋ฐ๋ผ ์คํ ํฌ๊ธฐ๋ฅผ ๋์ ์ผ๋ก ์กฐ์ ํฉ๋๋ค. ์๋ฐ 21์ ๊ฐ์ ์ค๋ ๋ ๋ํ ๋ธ๋กํน I/O ๋ฐ์ ์ ์ปค๋ ์ค๋ ๋๋ฅผ ์ ์ ํ์ง ์๊ณ ์๋ณด(Yield)ํ๋ ๋ฉ์ปค๋์ฆ์ ํตํด ์๋ง์ ์คํ ํ๋ฆ์ ๋์์ ์ฒ๋ฆฌํ ์ ์๊ฒ ํฉ๋๋ค.
M:N ๋ชจ๋ธ์ ๋ชจ๋ํฐ๋ง ๋น์ฉ
M:N ๋ชจ๋ธ์ ์ฑ๋ฅ ํจ์จ์ด ๋์ง๋ง, ์๋ฌ ๋ฐ์ ์ ์ถ์ ์ด ๋ณต์กํ๋ค๋ ๋จ์ ์ด ์์ต๋๋ค. ์ ์ ์ค๋ ๋์์ ๋ฐ์ํ ๋ฌธ์ ๊ฐ ์ด๋ ์ปค๋ ์ค๋ ๋ ๋ฌธ๋งฅ์์ ์คํ๋์๋์ง ํ์ ํ๊ธฐ ์ํด ๋ณ๋์ ๋ชจ๋ํฐ๋ง ๋๊ตฌ๊ฐ ํ์ํ ์ ์์ต๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
public class VirtualThreadDemo {
public static void main(String[] args) {
// 10๋ง ๊ฐ์ ๋์ ์์
์ํ. ๊ธฐ์กด ํ๋ซํผ ์ค๋ ๋(1:1 ๋ชจ๋ธ)๋ก๋ ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ(OOM)์ด ๋ฐ์ํ ์ ์๋ ๊ท๋ชจ์
๋๋ค.
int numTasks = 100_000;
System.out.printf("%d๊ฐ์ ๊ฐ์ ์ค๋ ๋ ์์
์์ฑ์ ์์ํฉ๋๋ค...\n", numTasks);
Instant start = Instant.now();
// Executors.newVirtualThreadPerTaskExecutor()๋ ๊ฐ ์์
๋ง๋ค ์๋ก์ด ๊ฐ์ ์ค๋ ๋๋ฅผ ์์ฑํฉ๋๋ค.
// try-with-resources ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ฉด ๋ธ๋ก์ ๋น ์ ธ๋๊ฐ ๋ executor.close()๊ฐ ํธ์ถ๋์ด
// ์ ์ถ๋ ๋ชจ๋ ์์
์ด ์๋ฃ๋ ๋๊น์ง ๋ฉ์ธ ์ค๋ ๋๊ฐ ๋๊ธฐํฉ๋๋ค (Structured Concurrency).
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, numTasks).forEach(i -> {
executor.submit(() -> {
try {
// ๊ฐ ์ค๋ ๋๋ I/O ์์
์ ์๋ฎฌ๋ ์ด์
ํ๊ธฐ ์ํด ์ ์ ๋๊ธฐํฉ๋๋ค.
// ๊ฐ์ ์ค๋ ๋๋ ๋ธ๋กํน ์ ์บ๋ฆฌ์ด ์ค๋ ๋(์ปค๋ ์ค๋ ๋)๋ฅผ ์ ์ ํ์ง ์๊ณ '์๋ณด(Yield)'ํฉ๋๋ค.
Thread.sleep(Duration.ofMillis(100));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
});
} // ์ฌ๊ธฐ์ ๋ชจ๋ ๊ฐ์ ์ค๋ ๋์ ์์
์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
Instant end = Instant.now();
System.out.printf("๋ชจ๋ ์์
์ด ์๋ฃ๋์์ต๋๋ค. ์์ ์๊ฐ: %d ms\n", Duration.between(start, end).toMillis());
// ๊ฒฐ๊ณผ์ ์ผ๋ก ์์์ ์ปค๋ ์ค๋ ๋๋ง์ผ๋ก 10๋ง ๊ฐ์ ๋
ผ๋ฆฌ์ ์คํ ํ๋ฆ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํด๋
๋๋ค.
}
}
Summary
ํ๋ ์ปดํจํ ๊ตฌ์กฐ๋ ํ๋ก์ธ์ค์ ๊ฒฉ๋ฆฌ์ ์ค๋ ๋์ ์์ ๊ณต์ ์ฌ์ด์ ๊ท ํ์ ๋ง์ถ๋ ๊ณผ์ ์ ๋๋ค. ์ด์์ฒด์ ๋ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ๊ณผ PCB๋ฅผ ํตํด ์์คํ ์์ ์ฑ์ ํ๋ณดํ๋ฉฐ, ์ฐ๊ธฐ ์ ๋ณต์ฌ์ M:N ์ค์ผ์ค๋ง์ ํตํด ํ๋์จ์ด ์์์ ํจ์จ์ ์ผ๋ก ํ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ปจํ ์คํธ ์ค์์นญ์ผ๋ก ์ธํ ์บ์ ์ค์ผ๊ณผ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์ ์ ๊ธ ๊ฒฝํฉ ๋ฌธ์ ๋ ์ฌ์ ํ ํด๊ฒฐํด์ผ ํ ๊ณผ์ ๋ก ๋จ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์๋น์ค์ ๋ถํ ํน์ฑ์ ๋ง๋ ์ ์ ํ ์คํ ๋ชจ๋ธ์ ์ ํํ๋ ์ค๊ณ ๋ฅ๋ ฅ์ด ์ค์ํฉ๋๋ค.



