[OS] I/O Models
๐งฉ I/O Model
์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ฝ๋๊ฐ ํ๋์จ์ด์ ๋ฌผ๋ฆฌ์ ์ค์ฒด์ ๋ฟ๊ธฐ๊น์ง๋ ์ด์์ฒด์ ๋ผ๋ ๊ฑฐ๋ํ ์ค์ฌ์๊ฐ ๋์ฌ ์์ต๋๋ค. ์ด ์ธ์์ ์ธ ์ธ๊ณ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค์ค๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ์ธ ๊ถํ์ด ์์ผ๋ฉฐ, ์ค์ง โ์์คํ ์ฝ(System Call)โ์ด๋ผ๋ ์๊ฒฉํ ํต๋ก๋ฅผ ํตํด ์ปค๋(Kernel)์๊ฒ ์์ ์ ๋ํํด ๋ฌ๋ผ๊ณ ์์ฒญํด์ผ ํฉ๋๋ค.
ํ๋ก์ธ์ค์ ์ถ์ํ
์ปดํจํฐ์ ๊ฐ์ฅ ์ค์ํ ๋ ํ๋์จ์ด ๊ตฌ์ฑ ์์์ธ CPU์ RAM์ ๊ฐ๊ฐ ์ฐ์ฐ์ ๋์ ๋จ๊ธฐ ๊ธฐ์ต ์ฅ์น๋ก์ ๋ง๋๋ณด๋๋ฅผ ํตํด ๊ธด๋ฐํ ํต์ ํฉ๋๋ค. ์ด์์ฒด์ ์ ๋ณธ์ง์ ์ธ ์ ๋ฌด๋ ์ด ๋ฌผ๋ฆฌ์ ์ธ ํ๋์จ์ด๋ค ์์ ํ๋ก์ธ์ค(Process)๋ผ๋ ๊ทผ๋ณธ์ ์ธ ์ถ์ํ ๊ณ์ธต์ ๊ตฌ์ถํ๋ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ๋ชจ๋ ์ํํธ์จ์ด๋ ์ด ํ๋ก์ธ์ค ๋ด๋ถ์์ ์คํ๋๋ฉฐ, ์ด๋ ํ๋์จ์ด์ ๋ณต์กํ ๋ฌผ๋ฆฌ์ ๋์์ ๊ฐ์ถ๊ณ ์ํํธ์จ์ด๊ฐ ์์ ํ๊ฒ ์์์ ์ ์ ํ ์ ์๋๋ก ๋ณดํธ๋ ์ธํ๋ฆฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ด์์ฒด์ ๊ฐ ์ ๊ณตํ๋ ์ด ๊ฐ์์ ์ธ๊ณ๋ ๊ฐ๋ ฅํ ๋ฉํฐํ์คํน ๊ธฐ๋ฅ์ ํตํด ์ฐ๋ฆฌ์๊ฒ ๋ง์น ์ฌ๋ฌ ํ๋ก๊ทธ๋จ์ด ๋์์ ์คํ๋๋ ๊ฒ ๊ฐ์ ํ์์ ์ฌ์ด์ค๋๋ค. ์ค์ ๋ก๋ ํ๋์ CPU ์ฝ์ด๊ฐ ์ ๋ฐ๋ฆฌ์ด ๋จ์๋ก ํ๋ก์ธ์ค๋ฅผ ๋ฒ๊ฐ์ ๊ฐ๋ฉฐ ์คํํ๋ ๊ฒ์ด์ง๋ง, CPU๋ ์ด๋น ์์ญ์ต ๊ฐ์ ๋ช ๋ น์ด๋ฅผ ์ฒ๋ฆฌํ ๋งํผ ์๋์ ์ผ๋ก ๋น ๋ฅด๊ธฐ์ ์ธ๊ฐ์ ๊ทธ ํ์๋ฅผ ์ธ์งํ์ง ๋ชปํฉ๋๋ค. ์ด๋ฌํ ์ ๊ตํ ์๊ฐ ์ชผ๊ฐ๊ธฐ(Time-slicing) ๊ธฐ์ ๋๋ถ์ ์ฐ๋ฆฌ๋ ํ๋์จ์ด์ ๋ฌผ๋ฆฌ์ ๊ฐ์๋ณด๋ค ํจ์ฌ ๋ง์ ์์ ์์ ์ ๋์์ ์ฒ๋ฆฌํ๋ ๋ ผ๋ฆฌ์ ํ์๋ก์์ ๋๋ฆฌ๊ฒ ๋ฉ๋๋ค.
ํ์ง๋ง ์ด ๊ฐ์์ ํ์๋ก์์ ๊ฒฐ์ฝ ๊ณต์ง๊ฐ ์๋๋๋ค. ํ๋ก์ธ์ค๋ฅผ ์ ํํ ๋๋ง๋ค ์ด์์ฒด์ ๋ ํ์ฌ ์คํ ์ค์ธ ํ๋ก์ธ์ค์ ๋ ์ง์คํฐ ์ํ๋ฅผ ์ ์ฅํ๊ณ ์ปค๋ ๋ชจ๋๋ก ์ง์ ํ๋ฉฐ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฑ์ ๋ณต์กํ ๋ท์ ๋ฆฌ๋ฅผ ์ํํด์ผ ํฉ๋๋ค. ์ด๋ฌํ ์ ํ ์์ ์ด ํ๋์ ์ธ ์์คํ ์์๋ ์๋นํ ์ฑ๋ฅ ๋น์ฉ์ ๋ฐ์์ํต๋๋ค. ๊ฒฐ๊ตญ I/O ๋ชจ๋ธ์ ๊น๊ฒ ์ดํดํ๋ค๋ ๊ฒ์, ์ด์์ฒด์ ๊ฐ ๊ตฌ์ถํ ํ๋ก์ธ์ค๋ผ๋ ์ถ์ํ ์ด๋ฉด์์ ํ๋์จ์ด ์์์ด ์ค์ ๋ก ์ด๋ป๊ฒ ๋ฐฐ๋ถ๋๊ณ ์๋ชจ๋๋์ง๋ฅผ ๊ฟฐ๋ซ์ด ๋ณด๋ ๊ณผ์ ๊ณผ ๊ฐ์ต๋๋ค.
์ ์ง์ฐ๋๋๊ฐ
์์ง๋์ด๋ง ๊ด์ ์์ I/O๋ โ์ง์ฐ๊ณผ์ ์ ์โ์ ๋๋ค. CPU๊ฐ ์ด๋น ์์ญ์ต ๊ฐ์ ๋ช ๋ น์ด๋ฅผ ์ฒ๋ฆฌํ๋ ๋์, ๋์คํฌ๋ ๋คํธ์ํฌ๋ ๊ทธ๋ณด๋ค ์๋ง ๋ฐฐ ๋๋ฆฐ ์๋๋ก ๋ฐ์ํฉ๋๋ค.
- CPU ์ ํด ์๊ฐ: ํ๋ ๋๋ผ์ด๋ธ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ค๋ ๊ฒ๊ณผ ๊ฐ์ ์ธ๋ถ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์, CPU๋ ์๋ฌด๋ฐ ์ ์ฉํ ์์ ๋ ํ์ง ๋ชปํ ์ฑ โ๋๊ธฐ(Waiting)โ ์ํ๋ก ์ ์ด๋ฉ๋๋ค.
- ๋ฌธ๋งฅ ์ ํ(Context Switching): ์คํ ์ค์ธ ํ๋ก์ธ์ค๊ฐ I/O๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ์๋ฆฌ๋ฅผ ๋น์ธ ๋ ๋ฐ์ํ๋ ์ ํ ๋น์ฉ์ ์ฝ 5๋ง์ดํฌ๋ก์ด์ ๋ฌํ๋ฉฐ, ์ด๋ ์๋ง ๊ฐ์ ๋ช ๋ น์ด ์คํ ๊ธฐํ๋ฅผ ์๋นํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
๋ฐ์ดํฐ ๋ณต์ฌ์ ๋ฉ๋ชจ๋ฆฌ ๊ฒฝ๊ณ์
๋จ์ํ ๊ธฐ๋ค๋ฆผ๋ง์ด ๋ฌธ์ ๊ฐ ์๋๋๋ค. ๋ฐ์ดํฐ๊ฐ ํ๋์จ์ด์์ ์ ํ๋ฆฌ์ผ์ด์ ๊น์ง ์ ๋ฌ๋๋ ๊ณผ์ ์๋ โ๋ฐ์ดํฐ ๋ณต์ฌ(Data Copy)โ๋ผ๋ ์จ์ ๋น์ฉ์ด ์กด์ฌํฉ๋๋ค.
- ์ปค๋ ๋ฒํผ ์ ์ : ํ๋์จ์ด ์ฅ์น ๋๋ผ์ด๋ฒ๊ฐ ์ฝ์ด์จ ๋ฐ์ดํฐ๊ฐ ์ปค๋ ์์ญ์ ๋ฉ๋ชจ๋ฆฌ์ ๋จผ์ ์ฑ์์ง๋๋ค.
- ์ ์ ์์ญ ๋ณต์ฌ: ์ปค๋์ ์์ ์ ๋ฒํผ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ ์์ญ ๋ฉ๋ชจ๋ฆฌ๋ก ๋ณต์ฌํฉ๋๋ค.
์ด ์ด์ค์ ์ธ ๋ณต์ฌ ๊ณผ์ ์ ๋ฉ๋ชจ๋ฆฌ ๋์ญํญ์ ์๋ชจํ๊ณ CPU ๋ถํ๋ฅผ ๋๋ฐํฉ๋๋ค. ๊ฒฐ๊ตญ ๊ณ ์ฑ๋ฅ ์์คํ ์ ์ค๊ณํ๋ค๋ ๊ฒ์ ์ด ๋ฐ์ดํฐ์ ํ๋ฆ๊ณผ CPU์ ๋๊ธฐ ์ํ๋ฅผ ์ผ๋ง๋ ์ ๊ตํ๊ฒ ์ฅ์ ํ๋๋์ ๋ฌ๋ ค ์์ต๋๋ค.
I/O ๋ชจ๋ธ ์ ํ์ ๋ณธ์ง
์ด๋ค I/O ๋ชจ๋ธ์ ์ ํํ๋๋๋ ๊ฒฐ๊ตญ โCPU๊ฐ ์ธ๋ถ ๋ฐ์ดํฐ๊ฐ ์ฌ ๋๊น์ง ๋ฌธ์ ์ ๊ทธ๊ณ ๊ธฐ๋ค๋ฆด ๊ฒ์ธ๊ฐ, ์๋๋ฉด ๋ค๋ฅธ ์ผ์ ํ๋ฉฐ ์ฃผ๊ธฐ์ ์ผ๋ก ํ์ธํ ๊ฒ์ธ๊ฐโ์ ๋ํ ์ ๋ต์ ๊ฒฐ์ ์ ๋๋ค.
๐งฉ Blocking
๊ฐ์ฅ ์ง๊ด์ ์ด๋ฉฐ ์์ด์ ์ธ ์ด ๋ชจ๋ธ์ โ๊ธฐ๋ค๋ฆผโ์ ์์ง๋์ด๋ง์ ์ค์ฌ์ ๋ก๋๋ค. ์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋๊ฐ ์์ผ์์ read()๋ฅผ ํธ์ถํ๋ ์๊ฐ, ์ปค๋ ๋ฒํผ์ ๋ฐ์ดํฐ๊ฐ ์ค๋น๋์ด ์์ง ์๋ค๋ฉด ์คํ ํ๋ฆ์ ๊ทธ ์๋ฆฌ์์ ์ฆ์ ๋ฉ์ถฐ ์๊ฒ ๋ฉ๋๋ค. ์ด๋ ๋จ์ํ ์ฝ๋์ ํ ์ค์ด ๋ฉ์ถ๋ ๊ฒ์ ๋์ด, ์ด์์ฒด์ ์์ค์์ ํ๋ก์ธ์ค์ ์๋ช
์ฃผ๊ธฐ๊ฐ ์ผ์์ ์ผ๋ก ์ค๋จ๋จ์ ์๋ฏธํฉ๋๋ค. ์ด์์ฒด์ ์ ํต์ฌ ์ญํ ์ ํ๋์จ์ด ์์์ ์ถ์ํํ์ฌ ๊ด๋ฆฌํ๋ ๊ฒ์ด๋ฉฐ, Blocking ํธ์ถ ์ ์ปค๋์ ํด๋น ํ๋ก์ธ์ค๋ฅผ โ์คํ(Running)โ ์ํ์์ โ๋๊ธฐ(Waiting)โ ์ํ๋ก ์ ์ด์์ผ CPU ์ค์ผ์ค๋ง ๋์์์ ์์ ํ ์ ์ธํฉ๋๋ค.
์ด ๊ณผ์ ์์ ์ปค๋์ ํ๋ก์ธ์ค์ ๋ฌธ๋งฅ(Context)์ ์ ์ฅํ๊ณ , ํ๋ก์ธ์ค ์ ์ด ๋ธ๋ก(PCB)์ ์คํ ํ์์ ์ ๊ฑฐํ์ฌ ํน์ ์ฅ์น์ wait_queue๋ก ์ด๋์ํต๋๋ค. CPU๋ ์ด์ ํ ์ผ์ด ์์ด์ง ๋๊ธฐ ํ๋ก์ธ์ค๋ฅผ ๋ ๋ ๋ค๋ฅธ ์คํ ๊ฐ๋ฅํ ์์
์ ์ฐพ์ ๋ ๋๋๋ฐ, ์ด ๋ฌธ๋งฅ ์ ํ ๊ณผ์ ์์ ๋ฐ์ํ๋ ์ง์ฐ์ด ์ฝ 5๋ง์ดํฌ๋ก์ด์ ๋ฌํฉ๋๋ค. ์ด๋ CPU๊ฐ ์๋ง ๊ฐ์ ๋ช
๋ น์ด๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ์ฒ๊ธ ๊ฐ์ ๊ธฐํ๋ฅผ ๋จ์ํ โ์์
ํ๊ฒฝ์ ๊ต์ฒดํ๋ ๋ฐโ ์จ๋ฒ๋ฆฌ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
์ด๋ฌํ ํ๋์จ์ด์ ์ปค๋ ์ฌ์ด์ ๋ณต์กํ ์ํธ์์ฉ, ์ฆ ์์คํ ์ฝ ํธ์ถ๋ถํฐ ํธ๋ฉ(Trap) ๋ฐ์, ์ปค๋ ๋ฒํผ ํ์ธ, ํ๋ก์ธ์ค ์๋ฉด ์ํ ์ง์ , ๊ทธ๋ฆฌ๊ณ ์ธํฐ๋ฝํธ์ ์ํ ๊นจ์ด๋จ์ผ๋ก ์ด์ด์ง๋ ์ผ๋ จ์ ๋ฉ์ปค๋์ฆ์ ์๋์ ์ฝ๋ ๊ตฌ์กฐ ์์ ์์ธํ ๋ น์ ์์ต๋๋ค.
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
38
39
40
41
42
43
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
/**
* C ๊ธฐ๋ฐ Blocking ์์ผ I/O ๋ฉ์ปค๋์ฆ
* * ์ด ์ฝ๋๋ ๊ฐ์ฅ ์ ํ์ ์ธ Blocking ๋ชจ๋ธ์ ๋ณด์ฌ์ค๋๋ค.
* ์ด์์ฒด์ ๋ ํ๋์จ์ด ์์์ ๋ณดํธํ๊ธฐ ์ํด
* ํ๋ก์ธ์ค์ ์ง์ ์ ์ธ ์ ์ด๊ถ์ ์ฃผ์ง ์๊ณ '์์คํ
์ฝ'์ด๋ผ๋ ์ค์ฌ์์ ์ ์ํฉ๋๋ค.
*/
void start_blocking_server(int client_fd) {
char buffer[1024];
printf("๋ฐ์ดํฐ ์์ ๋๊ธฐ ์ค...\n");
/* * 1. ์์คํ
์ฝ ์ง์
(Trap):
* ์ ์ ๋ชจ๋์์ ์ปค๋ ๋ชจ๋๋ก ์คํ ๊ถํ์ด ์ ํ๋ฉ๋๋ค.
* * 2. ์ปค๋ ๋ฒํผ ํ์ธ:
* ์ปค๋์ ํด๋น ์์ผ์ ์์ ๋ฒํผ์ ๋ฐ์ดํฐ๊ฐ ์๋์ง ํ์ธํฉ๋๋ค.
* * 3. ํ๋ก์ธ์ค ์ ๋ค๊ธฐ (Waiting State):
* ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด, ์ปค๋์ ์ด ์ค๋ ๋์ PCB(Process Control Block)๋ฅผ
* ์คํ ํ์์ ์ ๊ฑฐํ๊ณ 'Wait Queue'๋ก ์ด๋์ํต๋๋ค.
* * 4. ๋ฌธ๋งฅ ์ ํ (Context Switch):
* CPU๋ ํ์ฌ ์ค๋ ๋์ ๋ ์ง์คํฐ ์ํ๋ฅผ ์ ์ฅํ๊ณ ๋ค๋ฅธ ์์
์ ์ํํ๋ฌ ๋ ๋ฉ๋๋ค.
* ์ด ์ ํ์ ์ฝ 5๋ง์ดํฌ๋ก์ด๊ฐ ์์๋ฉ๋๋ค.
*/
ssize_t bytes_read = read(client_fd, buffer, sizeof(buffer));
/*
* 5. ์ธํฐ๋ฝํธ ๋ฐ ๊นจ์ด๋จ (Ready State):
* ์ฅ์น ๋๋ผ์ด๋ฒ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ฉด CPU์ ์ธํฐ๋ฝํธ๋ฅผ ๋ณด๋ด๊ณ ,
* ์ปค๋์ ์ ๋ค์๋ ํ๋ก์ธ์ค๋ฅผ ๋ค์ 'Ready' ์ํ๋ก ์ ํํฉ๋๋ค.
* * 6. ๋ฐ์ดํฐ ๋ณต์ฌ ๋ฐ ๋ณต๊ท:
* ์ปค๋ ๋ฒํผ์ ๋ฐ์ดํฐ๊ฐ ์ ์ ์์ญ์ buffer[]๋ก ๋ณต์ฌ๋ ํ,
* ๋น๋ก์ read() ํจ์๊ฐ ๋ฐํ๋๋ฉฐ ์ ์ด๊ถ์ด ๋ค์ ์ ์ ์๊ฒ ๋์์ต๋๋ค.
*/
if (bytes_read > 0) {
printf("์์ ๋ฐ์ดํฐ: %.*s\n", (int)bytes_read, buffer);
}
close(client_fd);
}
Blocking ๋ชจ๋ธ์ ์ง์ ํ ์ํ์ ๋จ์ํ ์๊ฐ ์ง์ฐ๋ณด๋ค โ์์ ์ค์ผโ์ ๊ฐ๊น์ต๋๋ค. ํ๋ก์ธ์ค๊ฐ CPU์์ ์ซ๊ฒจ๋ ๋, ํด๋น ํ๋ก์ธ์ค๊ฐ ์ฌ์ฉํ๋ L1, L2 ์บ์ ๋ฐ์ดํฐ๋ ๋ฌดํจํ(Flush)๋ฉ๋๋ค. ์ดํ ๋ฐ์ดํฐ๊ฐ ๋์ฐฉํ์ฌ ํ๋ก์ธ์ค๊ฐ ๋ค์ ๋ณต๊ทํ์ ๋ ์ง๋ฉดํ๋ โ์บ์ ๋ฏธ์ค(Cache Miss)โ๋ ์์คํ ์ ์ ์ฒด์ ์ธ ์ฒ๋ฆฌ๋(Throughput)์ ๊ฐ์๋จน๋ ์ฃผ๋ฒ์ด ๋ฉ๋๋ค. ๋ํ, ๊ณ ์ ์ ์ธ โ์ฐ๊ฒฐ๋น ์ค๋ ๋ ํ๋โ ๋ชจ๋ธ์ ์ฌ์ฉํ ๊ฒฝ์ฐ, ์๋ง ๊ฐ์ ์ค๋ ๋๊ฐ ๊ฐ์ Blocking ์ํ๋ก ์ ๋ค๊ฒ ๋๋ฉด ์ปค๋์ ์ด๋ค์ ๊ด๋ฆฌํ๊ณ ์ ํํ๋ ๋น์ฉ๋ง์ผ๋ก ์ ์ฒด ์์์ ์๋น ๋ถ๋ถ์ ํ์งํ๊ฒ ๋ฉ๋๋ค.
Blocking I/O์ ๊ตฌํ์ ๊ฐ์น
Blocking ๋ชจ๋ธ์ ์ฑ๋ฅ ์ต์ ํ ๊ด์ ์์๋ ๋ถ๋ฆฌํ ์ ์์ผ๋, ๋น์ฆ๋์ค ๋ก์ง์ ์์ฐจ์ ํ๋ฆ๊ณผ ์ฝ๋์ ์คํ ํ๋ฆ์ด 1:1๋ก ์ผ์นํ๋ค๋ ๊ฐ๋ ฅํ ๊ฐ์ ์ ๊ฐ์ง๋๋ค. ์ด๋ ๋๋ฒ๊น ์ ์ฉ์ด์ฑ๊ณผ ์ฝ๋์ ๋ช ํ์ฑ์ ๋ณด์ฅํ๋ฏ๋ก, ๋์์ฑ๋ณด๋ค๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ์ ํ์ฑ๊ณผ ์ ํ ๊ด๊ณ๊ฐ ํต์ฌ์ธ ๊ธ์ต๊ถ์ ๋ฐฐ์น ์์ ์ด๋ ํธ๋์ญ์ ๋๋ฉ์ธ์์ ์ฌ์ ํ ํ์ค์ ์ธ ์ ๋ต์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
๐งฉ Non-Blocking
Non-Blocking ๋ชจ๋ธ์ ์์คํ
์ฝ์ ๋ฐํ ์์ ์ ๋นํ์ด Blocking์ ๊ณ ์ง์ ์ธ ๋ฌธ์ ์ธ โ๋๊ธฐ ์ํ๋ก์ ์ ์ดโ๋ฅผ ์ ๋ฉด์ผ๋ก ๊ฑฐ๋ถํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์
์ด ์ปค๋์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ์ ๋, ์ค๋น๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด ์ปค๋์ ํ๋ก์ธ์ค๋ฅผ ์ ์ฌ์ฐ๋ ๋์ ์ฆ์ ์๋ฌ ์ฝ๋(EAGAIN ํน์ EWOULDBLOCK)๋ฅผ ์ ์ ์คํ์ด์ค๋ก ๋์ง๋๋ค. ์ด์์ฒด์ ์ ํต์ฌ ์ญํ ์ ํ๋ก์ธ์ค๊ฐ ์์์ ํจ์จ์ ์ผ๋ก ์ฐ๊ฒ ๋๋ ๊ฒ์ด๋ฉฐ, Non-Blocking ํธ์ถ์ ํ๋ก์ธ์ค๊ฐ โ๋๊ธฐ(Waiting)โ ์ํ๋ก ๋น ์ง์ง ์๊ณ โ์คํ(Running)โ ์ํ๋ฅผ ์ ์งํ๊ฒ ๋ง๋๋ ๊ฒฐ์ ์ ์ธ ๋๋ ฅ์ด ๋ฉ๋๋ค. ํ๋ก์ธ์ค๋ ์ ์ด๊ถ์ ์์ง ์์๊ธฐ์ ๋ฉ์ถ์ง ์๊ณ ๋ค์ ์ฐ์ฐ์ ์ํํ๊ฑฐ๋ ๋ ๋ค๋ฅธ I/O ์์ฒญ์ ๋ณด๋ด๋ฉฐ CPU ์์์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ ์ ํ ์ ์๋ ๊ถ๋ฆฌ๋ฅผ ํ๋ณดํฉ๋๋ค.
์ด๋ฌํ ์์ ์ ๋๊ฐ๋ โ๋ฐ๋ณต์ ์ธ ์ง์(Polling)โ๋ผ๋ ํ๋ฒ๋ก ๋์์ต๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ธ์ ์ค๋น๋ ์ง ์ ์ ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ปค๋์๊ฒ ์ํ๋ฅผ ๋์์์ด ์ฌํ์ธํด์ผ ํฉ๋๋ค. ์ด๋ฌํ ๋ฐ์ ๋๊ธฐ(Busy Wait)๋ CPU ์ฌ์ฉ๋ฅ ์ ๋ฌด์๋ฏธํ๊ฒ ์น์๊ฒ ๋ง๋ญ๋๋ค. ์ค์ ๋ก ๋ฐ์ดํฐ๊ฐ ๋์ฐฉํ์ง ์์ ์ฐฐ๋์ ์๊ฐ์๋ CPU๋ ๋ฃจํ๋ฅผ ๋๋ฉฐ ์์คํ ์ฝ์ ํธ์ถํด์ผ ํ๋ฉฐ, ์ด๋ ์ ์ ๋ชจ๋์ ์ปค๋ ๋ชจ๋๋ฅผ ์ค๊ฐ๋ โ๋ชจ๋ ์ ํ(Mode Switching)โ ๋น์ฉ์ ๋ฐ์์ํต๋๋ค. ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ด ํ๋ก์ธ์ค ๊ฐ์ ๋ฌผ๋ฆฌ์ ์ธ ์ ํ ๋น์ฉ์ด๋ผ๋ฉด, Non-Blocking์ Polling์ โ๋น ์๋์ ์๋ง ๋ฒ ์ด์ด๋ณด๋ ์ ์ /์ปค๋ ๊ฒฝ๊ณ ์๋ณต ๋น์ฉโ์ ๋น์ ํ ์ ์์ต๋๋ค.
์ด๋ฌํ ํ๋์จ์ด์ ์ปค๋ ์ฌ์ด์ ์ํธ์์ฉ, ํนํ ์ ์ด๊ถ์ ์ฆ์ ๋ฐํ๊ณผ EAGAIN ์๋ต์ ์ฒ๋ฆฌํ๋ฉฐ CPU๊ฐ ์ฌ์ง ์๊ณ ํ์ (Spin)ํ๋ ๊ณผ์ ์ ์๋์ ์ฝ๋ ๊ตฌ์กฐ ์์ ์์ธํ ๋
น์ ์์ต๋๋ค.
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
/**
* Non-Blocking ์์ผ ์ค์ ๋ฐ Polling ๋ฉ์ปค๋์ฆ
* * Non-Blocking ๋ชจ๋ธ์ ํต์ฌ์ '๊ธฐ๋ค๋ฆฌ์ง ์๋ ์ฉ๊ธฐ'์ '๋์์๋ ํ์ธ'์ ์์ต๋๋ค.
* ํ๋ก์ธ์ค๋ Waiting ์ํ๋ก ์ ์ด๋์ง ์๊ณ
* ๊ณ์ CPU๋ฅผ ์ ์ ํ๋ฉฐ ๋ก์ง์ ์ํํ ์ ์๋ ๊ถ๋ฆฌ๋ฅผ ์ ์งํฉ๋๋ค.
*/
void start_non_blocking_polling(int sockfd) {
char buffer[1024];
// 1. ์์ผ์ Non-Blocking ๋ชจ๋๋ก ์ ํํฉ๋๋ค.
// ์ด์ ์ด ์์ผ์ ๋์์ผ๋ก ํ๋ ์์คํ
์ฝ์ ์ ์ด๊ถ์ ์ฆ์ ๋ฐํํฉ๋๋ค.
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
printf("๋น์ฐจ๋จ ๋ชจ๋์์ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ํ์ธํฉ๋๋ค (Polling)...\n");
while (1) {
/*
* 2. ์ ์ด๊ถ ์ฆ์ ๋ฐํ (Immediate Return):
* read() ํธ์ถ ์ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด ์ปค๋์ ํ๋ก์ธ์ค๋ฅผ ์ ์ฌ์ฐ์ง ์์ต๋๋ค.
* ๋์ EAGAIN ๋๋ EWOULDBLOCK ์๋ฌ๋ฅผ ์ฆ์ ๋ฐํํ๋ฉฐ ์ ์ด๊ถ์ ๋๋ ค์ค๋๋ค.
*/
ssize_t bytes_read = read(sockfd, buffer, sizeof(buffer));
if (bytes_read == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
/*
* 3. ๋ฐ์ ๋๊ธฐ (Busy Wait/Spinning):
* ๋ฐ์ดํฐ๊ฐ ์์ง ๋์ฐฉํ์ง ์์์ต๋๋ค. ํ๋ก์ธ์ค๋ ์ฌ๊ธฐ์ ๋ฉ์ถ์ง ์๊ณ
* ๋ค๋ฅธ ์ฐ์ฐ์ ์ํํ๊ฑฐ๋, ๋ค์ ์์คํ
์ฝ์ ํธ์ถํ ์ค๋น๋ฅผ ํฉ๋๋ค.
* * ์ฃผ์: ์ด ๋ฃจํ๋ CPU ์ฌ์ฉ๋ฅ ์ 100%๊น์ง
* ์น์๊ฒ ๋ง๋ค๋ฉฐ ์ ์ /์ปค๋ ๊ฒฝ๊ณ๋ฅผ ์๋ณตํ๋ ๋ชจ๋ ์ ํ ๋น์ฉ์ ๋ฐ์์ํต๋๋ค.
*/
printf("๋ฐ์ดํฐ ๋ฏธ๋์ฐฉ. ๋ค๋ฅธ ์์
์ํ ์ค...\n");
// ์ค์ ๊ณ ์ฑ๋ฅ ์๋ฒ๋ผ๋ฉด ์ฌ๊ธฐ์ ๋ค๋ฅธ ์ ์๋ฏธํ ์์
์ ์ํํฉ๋๋ค.
do_other_business_logic();
continue;
}
break; // ์ค์ ์๋ฌ ๋ฐ์ ์ ๋ฃจํ ์ข
๋ฃ
}
/*
* 4. ๋ฐ์ดํฐ ํ๋:
* ์ฌ๋ฌ ๋ฒ์ Polling ๋์ ๋ฐ์ดํฐ๊ฐ ๋ฒํผ์ ์ฐจ๋ ์๊ฐ,
* ์์คํ
์ฝ์ ๋น๋ก์ ์ ์๋ฏธํ ๋ฐ์ดํธ ์๋ฅผ ๋ฐํํฉ๋๋ค.
*/
if (bytes_read > 0) {
printf("์์ ์ฑ๊ณต: %.*s\n", (int)bytes_read, buffer);
break;
}
}
}
Non-Blocking ๋ชจ๋ธ์ ํจ์จ์ ์๊ณ์
Non-Blocking I/O๋ ๋จ์ผ ์ค๋ ๋๊ฐ ์์ฒ ๊ฐ์ ์ฐ๊ฒฐ์ ๋์์ ๊ด๋ฆฌํ ์ ์๋ ์ํคํ ์ฒ์ ๊ธฐ๋ฐ์ ์ ๊ณตํ์ง๋ง, Polling์ ๋ฐ๋๊ฐ ๋์์ง์๋ก CPU ํจ์จ์ ๊ธ๊ฒฉํ ํ๋ฝํฉ๋๋ค. ๋ฐ๋ผ์ ์ค์ ์์ง๋์ด๋ง์์๋ ์ด๋ฅผ ๋จ๋ ์ผ๋ก ์ฐ๊ธฐ๋ณด๋ค ์ปค๋์ด ์ด๋ฒคํธ ๋ฐ์์ ์๋ ค์ฃผ๋ ๋ฉํฐํ๋ ์ฑ ๊ธฐ์ ๊ณผ ๊ฒฐํฉํ์ฌ, CPU๊ฐ โ์ ์๋ฏธํ ์ ํธโ๊ฐ ์์ ๋๋ง ์์ง์ด๋๋ก ์ค๊ณํ๋ ๊ฒ์ด ํต์ฌ์ ๋๋ค.
๐งฉ Synchronous
Synchronous(๋๊ธฐ) ๋ชจ๋ธ์ โ์์ ์ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์ฃผ์ฒดโ๊ฐ ๋๊ตฌ์ธ์ง, ๊ทธ๋ฆฌ๊ณ ์ ์ด ํ๋ฆ๊ณผ ๋ฐ์ดํฐ์ ํ๋ฆ์ด ์ด๋ป๊ฒ ๋ง๋ฌผ๋ฆฌ๋์ง์ ์ง์คํฉ๋๋ค. ์ด ๋ชจ๋ธ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ปค๋์๊ฒ ์์ฒญํ ์์ ์ด ๋๋ ๋๊น์ง ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ์ง์ ์ฑ๊ฒจ์ผ ํ ์๋ฌด๊ฐ ์์ต๋๋ค. ๋ง์ ์ด๋ค์ด Blocking๊ณผ Synchronous๋ฅผ ํผ๋ํ์ง๋ง, ์ด ๋์ ์๋ฐํ ๋ค๋ฅธ ์ธต์์ ๊ฐ๋ ์ ๋๋ค. ํ๋ก์ธ์ค๋ ์ด์์ฒด์ ๊ฐ ์ ๊ณตํ๋ ๋ช ๋ น์ด์ ์์ฐจ์ ์คํ ๋จ์์ด๋ฉฐ, ๋๊ธฐ ๋ชจ๋ธ์ ์ด ์์ฐจ์ฑ์ ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ํ๋ ๋ฐฉ์์ ๋๋ค. ์ค๋ น Non-Blocking ํธ์ถ์ ํตํด ์ ์ด๊ถ์ ์ฆ์ ๋๋ ค๋ฐ์๋ค ํ๋๋ผ๋, ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ฃจํ๋ฅผ ๋๋ฉฐ ๋ฐ์ดํฐ๊ฐ ๋์ฐฉํ๋์ง ์ง์ ํ์ธํ๊ณ ์๋ค๋ฉด ์ด๋ ์ฌ์ ํ ๋๊ธฐ์ ํ๋ฆ์ ํด๋นํฉ๋๋ค. ์คํ ํ๋ฆ(Control Flow)๊ณผ ๋ฐ์ดํฐ์ ์์ฑ(Data Completion)์ด ๋ ผ๋ฆฌ์ ์ผ๋ก ๊ฐํ๊ฒ ๊ฒฐํฉ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
ํ๋ก์ธ์ค ์ถ์ํ ๊ด์ ์์ ๋๊ธฐ ๋ชจ๋ธ์ ์ธ๊ณผ๊ด๊ณ๊ฐ ๋ช ํํ ์ง๋ ฌ์ ์ธ๊ณ๋ฅผ ๊ตฌ์ถํฉ๋๋ค. ํ๋์ ์์ฒญ์ด ๋ฐ์ํ๊ณ , ๊ทธ์ ๋ฐ๋ฅธ ์์ ์ด ์ํ๋๋ฉฐ, ๊ฒฐ๊ณผ๊ฐ ๋ฐํ๋๋ ๊ณผ์ ์ด ๋จ์ผํ ์ ํ์ ํ์๋ผ์ธ ์์ ๋์ ๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ๋ ๊ฐ๋ฐ์์๊ฒ ๊ฐ๋ ฅํ ์์ธก ๊ฐ๋ฅ์ฑ์ ์ ๊ณตํ์ง๋ง, ์์คํ ์ ์ ์ฒด ์ฒ๋ฆฌ ์๋๊ฐ ๊ฐ์ฅ ๋๋ฆฐ ๊ตฌ์ฑ ์์์ธ I/O ์ฅ์น์ ์ฑ๋ฅ์ ์ข ์๋๋ ๋ณ๋ชฉ ํ์์ ์ผ๊ธฐํฉ๋๋ค. 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
/**
* Synchronous ๋ชจ๋ธ์ ๋
ผ๋ฆฌ์ ํ๋ฆ
* * ๋๊ธฐ ๋ชจ๋ธ์ ํต์ฌ์ '๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์ฃผ์ฒด'๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์์ ์ด๋ผ๋ ์ ์
๋๋ค.
* ํ๋ก์ธ์ค ์ถ์ํ ๊ด์ ์์ ๋ณด๋ฉด, ์ด๋ ๋ช
๋ น์ด์ ์์ฐจ์ ์คํ์
* ๋
ผ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ํ์ฌ ๋ฐ์ดํฐ์ ์ ํฉ์ฑ์ ํ๋ณดํ๋ ๊ฐ์ฅ ํ์คํ ๋ฐฉ๋ฒ์
๋๋ค.
*/
void synchronous_data_processing(int sockfd) {
char buffer[1024];
/* * 1. ์์
์ ์์ฒญ๊ณผ ์ธ๊ณผ์ ๊ฒฐํฉ:
* ํธ์ถ์๋ ์ปค๋์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ ํ, ํด๋น ๋ฐ์ดํฐ๊ฐ ์ ์ ์์ญ์
* ๋ฉ๋ชจ๋ฆฌ์ ์์ ํ ๋ณต์ฌ๋ ๋๊น์ง ์ด ์์
์ ์ปจํ
์คํธ๋ฅผ ์ ์งํฉ๋๋ค.
*/
printf("๋๊ธฐ์ ๋ฐ์ดํฐ ํ๋ ์์...\n");
/* * 2. Blocking-Sync vs Non-Blocking-Sync:
* - Blocking-Sync: ์๋ read()์์ ํ๋ก์ธ์ค๊ฐ ์ ๋ค๋ฉฐ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆผ.
* - Non-Blocking-Sync: EAGAIN์ ๋ฐ๋๋ผ๋ ๋ฃจํ๋ฅผ ๋๋ฉฐ ์ง์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธ(Polling).
* * ์ด๋ค ๊ฒฝ์ฐ๋ '๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๊ณ ํ์ ์ง๋ ์ฃผ์ฒด'๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ด๋ฏ๋ก
* ์ด๋ ๋
ผ๋ฆฌ์ ์ผ๋ก ๋๊ธฐ(Synchronous) ์์
์ ํด๋นํฉ๋๋ค.
*/
ssize_t result = read(sockfd, buffer, sizeof(buffer));
/* * 3. ๊ฒฐ๊ณผ์ ์ฆ๊ฐ์ ์ฒ๋ฆฌ:
* ์ปค๋๋ก๋ถํฐ ์ ์ด๊ถ๊ณผ ํจ๊ป '์์ฑ๋ ๋ฐ์ดํฐ'๋ฅผ ๋๊ฒจ๋ฐ๋ ์๊ฐ
* ๋ค์ ๋ก์ง์ผ๋ก ์งํํฉ๋๋ค. ํ๋ก์ธ์ค์ ์ ํ์ ํ์๋ผ์ธ์ด ์ ์ง๋๋ ์ง์ ์
๋๋ค.
*/
if (result > 0) {
process_received_data(buffer, result);
}
// ์์
์ด ์์ ํ ๋๋ ํ์์ผ ๋ค์ ๋น์ฆ๋์ค ๋ก์ง์ด ์คํ๋ฉ๋๋ค.
printf("๋๊ธฐ์ ์์
์ข
๊ฒฐ. ๋ค์ ๋จ๊ณ๋ก ์ด๋ํฉ๋๋ค.\n");
proceed_to_next_step();
}
๋๊ธฐ ๋ชจ๋ธ์์์ ๋ฐ์ดํฐ ๋ณต์ฌ๋ ์ปค๋ ์คํ์ด์ค์ ์ ์ ์คํ์ด์ค ์ฌ์ด์ ์๊ฒฉํ ๊ฒฝ๊ณ์ ์์ ์ด๋ฃจ์ด์ง๋๋ค. ์ปค๋์ด ํ๋์จ์ด๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์์ ์ ๋ฒํผ๋ฅผ ์ฑ์ฐ๋ ๋์, ์ ํ๋ฆฌ์ผ์ด์ ์ โ๊ฒฐ๊ณผโ๋ผ๋ ์ํ๋ฅผ ์ป๊ธฐ ์ํด ๋๊ธฐํ๊ฑฐ๋ ์ฃผ๊ธฐ์ ์ผ๋ก ์ํ๋ฅผ ํ์ธํฉ๋๋ค. CPU์ RAM์ ๋ง๋๋ณด๋๋ฅผ ํตํด ๊ธด๋ฐํ ์ฐ๊ฒฐ๋์ด ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ง๋ง, ๋๊ธฐ์ I/O์์๋ ์ด ๋ฌผ๋ฆฌ์ ์๋๋ณด๋ค ์ปค๋์ ์์ ์๋ฃ ํต์ง๊ฐ ์ฐ์ ์๋ฉ๋๋ค. ๊ฒฐ๊ตญ ์ปค๋ ๋ฒํผ์์ ์ ์ ๋ฉ๋ชจ๋ฆฌ๋ก ๋ฐ์ดํฐ ๋ณต์ฌ๊ฐ ์๋ฃ๋๋ ์์ ์ด ๊ณง ๋๊ธฐ์ ์์ ์ ์ข ๊ฒฐ์ ์ด ๋ฉ๋๋ค.
๋๊ธฐ์ ์ฒ๋ฆฌ์ ๊ตฌ์กฐ์ ์์ ์ฑ ย ๋๊ธฐ ๋ชจ๋ธ์ ํธ์ถ์์ ํผํธ์ถ์ ์ฌ์ด์ ์ํ๊ฐ ํญ์ ์ผ์นํจ์ ๋ณด์ฅํฉ๋๋ค. ์ด๋ ๋ณต์กํ ๋ถ์ฐ ์์คํ ์ด๋ ๋ค์ค ์ค๋ ๋ ํ๊ฒฝ์์ ๋ฐ์ํ ์ ์๋ โ์ํ ๋ถ์ผ์นโ ๋ฌธ์ ๋ฅผ ์์ฒ ์ฐจ๋จํ๋ฉฐ, ๋ฐ์ดํฐ์ ์์ฐจ์ ์ ํฉ์ฑ์ด ๋ฌด์๋ณด๋ค ์ค์ํ ํธ๋์ญ์ ์ฒ๋ฆฌ ์์ญ์์ ์์คํ ์ ๋ณต์ก๋๋ฅผ ๋ฎ์ถ๊ณ ์์ ์ฑ์ ํ๋ณดํ๋ ๊ฒฐ์ ์ ์ธ ์ญํ ์ ์ํํฉ๋๋ค.
๐งฉ Asynchronous
Asynchronous(๋น๋๊ธฐ) ๋ชจ๋ธ์ โ๊ด์ฌ์ ์์ ํ ๋ถ๋ฆฌโ๋ฅผ ํตํด I/O ์ง์ฐ์ ๊ตด๋ ๋ฅผ ๋ฒ์ด๋์ง๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ์ปค๋์ I/O ์์ ์ ์์ฒญํจ๊ณผ ๋์์ ๊ทธ ์์ ์ ๋ํ ๋ชจ๋ ๊ถํ๊ณผ ์ฑ ์์ ๋๊น๋๋ค. โ๋ฐ์ดํฐ๊ฐ ์ค๋น๋๋ฉด ๋๋ฅผ ๊นจ์ฐ๊ฑฐ๋, ๋ด ๋ฉ๋ชจ๋ฆฌ์ ์ง์ ๋ฃ์ด๋ฌ๋ผโ๋ ๊ณ์ฝ์ ๋งบ๋ ๊ฒ์ ๋๋ค. ์ง์ ํ ๋น๋๊ธฐ ๋ชจ๋ธ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ I/O ์์ ์ด ์งํ๋๋ ๋์ ์์ ์ ๋ณธ๋ ์ ๋ฌด๋ฅผ ์ํํ๋ฉฐ, ์ปค๋์ด ๋ฐฐ๊ฒฝ(Background)์์ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ์ฑ์ด ๋ค ํต์ง(Notification)๋ฅผ ๋ณด๋ด๋ ์์ ์๋ง ๋ฐ์ํฉ๋๋ค. ์ด๋ CPU๊ฐ ์ ํด ์ํ๋ก ๋ญ๋น๋๋ ์๊ฐ์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ ๊ฑฐํ๋ ค๋ ์์ง๋์ด๋ง์ ์ ์์ ๋๋ค.
์ด ๋ชจ๋ธ์ ์ ์๋ ์ปค๋์ด ์ ์ ์คํ์ด์ค์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์ง์ ์จ์ฃผ๋ โProactorโ ํจํด์ ์์ต๋๋ค. ๊ธฐ์กด์ ๋๊ธฐ ๋ฐฉ์์ด โ๋ฐ์ดํฐ๊ฐ ์์ผ๋ ๊ฐ์ ธ๊ฐ๋ผโ๊ณ ์๋ ค์ฃผ๋ ์๋์ ํต์ง์๋ค๋ฉด, ๋น๋๊ธฐ๋ โ๋์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์ด๋ฏธ ๋ค ์ฑ์๋์์ผ๋ ๋ฐ๋ก ์ฐ๊ธฐ๋ง ํด๋ผโ๊ณ ํ์ธํฉ๋๋ค. CPU์ RAM ์ฌ์ด์ ๊ธด๋ฐํ ํ๋ ฅ์ ๊ฐ์ฅ ๊ทน๋ํํ๋ ๋ฐฉ์์
๋๋ค. ์ด๋ ์ ์ ์คํ์ด์ค์์์ ์ถ๊ฐ์ ์ธ ๋ฐ์ดํฐ ๋ณต์ฌ ๋น์ฉ์ ๊ทน๋จ์ ์ผ๋ก ๋ฎ์ถ๋ฉฐ, ๋ฆฌ๋
์ค์ io_uring์ด๋ ์๋์ฐ์ IOCP ๊ฐ์ ๊ธฐ์ ๋ค์ด ์งํฅํ๋ ๊ถ๊ทน์ ์ธ I/O ํจ์จ์ฑ์ ์์งํฉ๋๋ค.
์ด๋ฌํ ์ ์ด์ ์ญ์ , ์ฆ ์์ฒญ ์์ ๊ณผ ์๋ฃ ํต์ง ์์ ์ด ์์ ํ ๋ถ๋ฆฌ๋์ด ์คํ ํ๋ฆ์ด ํํธํ๋๋ ๋ฉ์ปค๋์ฆ์ ์๋์ ์ฝ๋ ๊ตฌ์กฐ ์์ ์์ธํ ๋ฌ์ฌ๋์ด ์์ต๋๋ค. ์์คํ ์ฝ์ด ์ฆ์ ๋ฐํ๋๋ ๊ฒ์ ๋์ด, ์์ ์ ์ข ๊ฒฐ ์ฃผ์ฒด๊ฐ ์ปค๋๋ก ๋์ด๊ฐ๋ ๊ณผ์ ์ ํ์ธํ ์ ์์ต๋๋ค.
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <aio.h>
/**
* Asynchronous I/O ์ธํฐํ์ด์ค ๋ชจ๋ธ
* * ๋น๋๊ธฐ ๋ชจ๋ธ์ ํต์ฌ์ '๊ถํ๊ณผ ์ฑ
์์ ์ ์ ์ธ ์ด์'์
๋๋ค.
* ์ด๋ CPU๊ฐ I/O ์ฅ์น์ ์๋ต์ ๊ธฐ๋ค๋ฆฌ๋
* 0.1%์ ์๊ฐ์กฐ์ฐจ ํ์ฉํ์ง ์๊ณ ์ค์ง ์ฐ์ฐ์๋ง ๋ชฐ์
ํ๊ฒ ๋ง๋๋ ๋ฐฉ์์
๋๋ค.
*/
void asynchronous_io_handler(sigval_t sig) {
struct aiocb *cbp = (struct aiocb *)sig.sival_ptr;
// 4. ์๋ฃ ํต์ง ๋ฐ ์ฒ๋ฆฌ (Callback/Notification):
// ์ปค๋์ด ์ ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ๋ค ์ฑ์ด ๋ค์์ผ ๋น๋ก์ ์ด ํจ์๊ฐ ํธ์ถ๋ฉ๋๋ค.
if (aio_error(cbp) == 0) {
ssize_t n = aio_return(cbp);
printf("\n[ํต์ง] ๋น๋๊ธฐ ์ฝ๊ธฐ ์๋ฃ: %.*s\n", (int)n, (char *)cbp->aio_buf);
}
}
void start_asynchronous_read(int sockfd) {
struct aiocb cb;
char buffer[1024];
memset(&cb, 0, sizeof(struct aiocb));
cb.aio_fildes = sockfd;
cb.aio_buf = buffer;
cb.aio_nbytes = sizeof(buffer);
// 1. ํต์ง ๋ฉ์ปค๋์ฆ ์ค์ :
// ๋ฐ์ดํฐ๊ฐ ์ค๋น๋๋ฉด ํธ์ถ๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ง์ ํฉ๋๋ค.
cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
cb.aio_sigevent.sigev_notify_function = asynchronous_io_handler;
cb.aio_sigevent.sigev_value.sival_ptr = &cb;
/*
* 2. ์์
์์ฒญ ๋ฐ ์ฆ์ ๋ฐํ (Request Submission):
* aio_read()๋ ์ปค๋์๊ฒ '๋์ค์ ์ฝ์ด์ ๋ด ๋ฉ๋ชจ๋ฆฌ์ ๋ฃ์ด๋ฌ๋ผ'๊ณ
* ๋ช
๋ น๋ง ๋ด๋ฆฐ ๋ค 0.0001์ด ๋ง์ ๋ฐํ๋ฉ๋๋ค.
*/
if (aio_read(&cb) == -1) {
perror("aio_read ์คํจ");
return;
}
/*
* 3. ๋
๋ฆฝ์ ์
๋ฌด ์ํ (Non-dependent Execution):
* ํ๋ก์ธ์ค์ 'Running' ์ํ๋ฅผ 100% ํ์ฉํฉ๋๋ค.
* I/O๊ฐ ๋ฐฐ๊ฒฝ์์ ๋์๊ฐ๋ ๋์, ๋ฉ์ธ ๋ก์ง์ ๋ฉ์ถ์ง ์๊ณ ์ฐ์ฐ์ ๊ณ์ํฉ๋๋ค.
*/
for (int i = 0; i < 5; i++) {
printf("๋ฉ์ธ ์ค๋ ๋๋ ๋ค๋ฅธ ์ฐ์ฐ ์ค... [%d]\n", i);
sleep(1);
}
}
๊ทธ๋ฌ๋ ๋น๋๊ธฐ ๋ชจ๋ธ์ โ์ธ์ง์ ๋ถํโ๋ผ๋ ๋์ ์ฒญ๊ตฌ์๋ฅผ ๋ด๋ฐ๋๋ค. ์์ ์ ์์ฒญ๊ณผ ์๋ฃ๊ฐ ์๊ฐ์ ์ผ๋ก ๊ฒฉ๋ฆฌ๋๋ฉด์ ํ๋ก๊ทธ๋จ์ ๋ ผ๋ฆฌ์ ์ ํ ๊ด๊ณ๊ฐ ๋ค์์ด๊ฒ ๋๊ณ , ์ด๋ ์คํ ์ถ์ (Stack Trace)์ ๋จ์ ๋ก ์ด์ด์ ธ ๋๋ฒ๊น ์ ๋ฏธ๋ก ์์ ๊ฐ๋ก๋๋ค. ๋ฌ์ฌํ ์ผ๊ด๋ ํ๋ก์ธ์ค์ ํ๋ฆ์ด ๋น๋๊ธฐ ์ธ๊ณ์์๋ ์๋ง์ ์ฝ๋ฐฑ๊ณผ ์ด๋ฒคํธ์ ํํธ์ผ๋ก ํฉ์ด์ง๊ฒ ๋ฉ๋๋ค. ์์ง๋์ด๋ ํฉ์ด์ง ํํธ๋ค์ ๋ชจ์ ํ๋์ ๋น์ฆ๋์ค ์ปจํ ์คํธ๋ก ์ฎ์ด๋ด๊ธฐ ์ํ ์ ๊ตํ ์ํ ๋จธ์ (State Machine)์ ๊ตฌ์ถํด์ผ ํ๋ ๊ณผ์ ๋ฅผ ๋ ์๊ฒ ๋ฉ๋๋ค.
๋น๋๊ธฐ ๋ชจ๋ธ์ ๋์ ๋น์ฉ๊ณผ ๊ฐ์น
๋น๋๊ธฐ I/O๋ ์ปค๋์ ์ ์ฌ๋ ฅ์ ๊ทนํ๊น์ง ๋์ด์ฌ๋ ค ์ต์ํ์ ์์์ผ๋ก ์๋ง ๊ฑด์ ๋์ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅ์ผ ํ์ง๋ง, ์ค๊ณ์ ๋ณต์ก๋์ ์ ์ง๋ณด์ ๋น์ฉ ์ญ์ ๊ธฐํ๊ธ์์ ์ผ๋ก ์์นํฉ๋๋ค. ๋จ์ํ ์ฑ๋ฅ ์์น์ ๋งค๋ชฐ๋๊ธฐ๋ณด๋ค, ์์คํ ์ ๊ท๋ชจ์ ํ์ ์๋ จ๋, ๊ทธ๋ฆฌ๊ณ ํด๋น OS ํ๊ฒฝ์ด ์ ๊ณตํ๋ ๋น๋๊ธฐ ํ๋ฆฌ๋ฏธํฐ๋ธ์ ์ฑ์๋๋ฅผ ๋ฉด๋ฐํ ๊ฒํ ํ์ฌ ๋์ ์ค์ต์ ๋ฐ์ ธ์ผ ํฉ๋๋ค.
Linux epoll
ํ๋ ๊ณ ์ฑ๋ฅ ์๋ฒ์ ์ญ์ฌ๋ โC10K ๋ฌธ์ (๋ง ๊ฐ์ ํด๋ผ์ด์ธํธ ๋์ ์ ์)โ๋ฅผ ์ด๋ป๊ฒ ํด๊ฒฐํ ๊ฒ์ธ๊ฐ์ ๋ํ ํฌ์์ ๊ธฐ๋ก์
๋๋ค. ๊ณผ๊ฑฐ์ select์ poll์ด ๊ฐ์ก๋ ๊ทผ๋ณธ์ ์ธ ํ๊ณ๋ ๊ฐ์ ๋์์ธ ์์ผ์ ์๊ฐ ๋์ด๋ ์๋ก ์ฑ๋ฅ์ด ์ ํ์ ์ผ๋ก ํ๋ฝ($O(N)$)ํ๋ค๋ ์ ์ด์์ต๋๋ค. ์ด์์ฒด์ ๋ ํ๋์จ์ด ์์์ ์ถ์ํํ์ฌ ๊ด๋ฆฌํ๋๋ฐ, ๋งค๋ฒ ์๋ง ๊ฐ์ ๋ฆฌ์คํธ๋ฅผ ์ปค๋๋ก ๋ณต์ฌํ๊ณ ์ฒ์๋ถํฐ ๋๊น์ง ํ์ด์ผ ํ๋ ๋ฐฉ์์ CPU ์ฐ์ฐ ์์์ ๋ญ๋น๋ฅผ ๋์ด ์์คํ
์ ์ฒด์ ์๋ต ์ง์ฐ์ ์ด๋ํฉ๋๋ค.
์ด๋ฌํ ๋นํจ์จ์ ํํํ๊ธฐ ์ํด ๋ฑ์ฅํ ๋ฆฌ๋
์ค์ epoll์ ๊ด์ ์ ์์ ํ ๋ฐ๊ฟ๋๋ค. ๋ฌธ์ ๋ฅผ โ์ํ์ ๋ฑ๋กโ๊ณผ โ์ด๋ฒคํธ์ ํต์งโ๋ก ๋ถ๋ฆฌํ ๊ฒ์
๋๋ค.
| ํน์ง | select / poll | epoll |
|---|---|---|
| ์๊ฐ ๋ณต์ก๋ | $O(N)$ (์ ์ฒด ๋ฃจํ ํ์) | $O(1)$ (์ด๋ฒคํธ ๋ฐ์ ๊ฑด๋ง ์ฒ๋ฆฌ) |
| ๊ด์ฌ ๋ฆฌ์คํธ ๊ด๋ฆฌ | ๋งค๋ฒ ์ ์ โ ์ปค๋ ๋ณต์ฌ | ์ปค๋ ๋ด๋ถ(Red-Black Tree)์์ ๊ด๋ฆฌ |
| ์ต๋ ์์ผ ์ | FD_SETSIZE ์ ํ (๊ธฐ๋ณธ 1024) | ์ ํ ์์ (์์คํ ์์ ํ์ฉ์น๊น์ง) |
| ์๋ฆผ ๋ฐฉ์ | โ์ด๋๊ฐ ๋ฐ์ดํฐ ์์ผ๋ ๋๊ฐ ์ฐพ์๋ดโ | โ์ด ์์ผ๋ค์ ๋ฐ์ดํฐ ์์ผ๋ ๊ฐ์ ธ๊ฐโ |
epoll์ ์ปค๋ ๋ด๋ถ์ ๋ ๋-๋ธ๋ ํธ๋ฆฌ(Red-Black Tree)๋ฅผ ๊ตฌ์ถํ์ฌ ๊ฐ์ ๋์ ์์ผ์ ๊ด๋ฆฌํฉ๋๋ค. ์์ผ ํ๋๊ฐ ์ถ๊ฐ๋๊ฑฐ๋ ์ญ์ ๋ ๋ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ํตํด ๋ก๊ทธ ์๊ฐ ๋ณต์ก๋๋ก ๋น ๋ฅด๊ฒ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ฉฐ, ๋ฐ์ดํฐ๊ฐ ์ค์ ๋ก ๋์ฐฉํ ์์ผ๋ค๋ง ๋ณ๋์ Ready List(๋งํฌ๋ ๋ฆฌ์คํธ)์ ๋ด์ต๋๋ค. CPU์ RAM ์ฌ์ด์ ๊ธด๋ฐํ ํ๋ ฅ์ ์ฌ๊ธฐ์ ๋น์ ๋ฐํฉ๋๋ค. ํ๋์จ์ด ์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ํ๋ฉด ์ปค๋์ ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ๋ฅผ ํตํด Ready List์ ํด๋น ์์ผ์ ์ฆ์ ์ง์ด๋ฃ๊ณ , ์ ํ๋ฆฌ์ผ์ด์
์ ์ด ๋ฆฌ์คํธ๋ง ์ฝ์ด ๊ฐ๋ฉด ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
์ฌ๊ธฐ์ ์์ง๋์ด๊ฐ ๋ฐ๋์ ๊ฒฐ์ ํด์ผ ํ ํธ๋ ์ด๋์คํ๋ Trigger ๋ฐฉ์์ ์ ํ์ ๋๋ค.
- Level-Triggered (LT): ๋ฐ์ดํฐ๊ฐ ๋ฒํผ์ ๋จ์ ์๋ ๋์ ๊ณ์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํต๋๋ค.
select์ ์ ์ฌํ์ฌ ๊ตฌํ์ด ์ฝ์ง๋ง, ๋ถํ์ํ ์ด๋ฒคํธ ํธ์ถ์ด ์ฆ์ ์ ์์ต๋๋ค. - Edge-Triggered (ET): ๋ฐ์ดํฐ๊ฐ ์ฒ์ ๋์ฐฉํ โ๋ณํ์ ์๊ฐโ์๋ง ๋ฑ ํ ๋ฒ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํต๋๋ค. Non-Blocking ์์ผ๊ณผ ๊ฒฐํฉํ์ฌ 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
38
39
40
41
42
43
44
45
46
47
48
49
#include <sys/epoll.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
/**
* Linux epoll์ ํ์ฉํ ์ด๋ฒคํธ ๋ฃจํ ๊ตฌํ
* * epoll์ ํต์ฌ์ '๊ด์ฌ์ ๋ฑ๋ก'๊ณผ 'ํต์ง์ ์์ '์ ๋ถ๋ฆฌํ๋ ๋ฐ ์์ต๋๋ค.
* ์ด์์ฒด์ ๋ ํ๋์จ์ด ์์์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํด
* ํ๋ก์ธ์ค ์ํ ์ ์ด๋ฅผ ์ ์ดํ๋ฉฐ, epoll์ ์ด ๊ณผ์ ์์ ๋ฐ์ํ๋
* ์ปจํ
์คํธ ์ค์์นญ๊ณผ ๋ฐ์ดํฐ ๋ณต์ฌ ๋น์ฉ์ ๊ทนํ์ผ๋ก ์ ๊ฐํฉ๋๋ค.
*/
void run_epoll_event_loop(int server_fd) {
// 1. epoll ์ธ์คํด์ค ์์ฑ
// ์ปค๋ ๋ด๋ถ์ ์ด๋ฒคํธ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ์ ์ฉ ๊ณต๊ฐ(๋ ๋-๋ธ๋ ํธ๋ฆฌ)์ ๋ง๋ จํฉ๋๋ค.
int epfd = epoll_create1(0);
struct epoll_event ev, events[MAX_EVENTS];
// 2. ์ฃ์ง ํธ๋ฆฌ๊ฑฐ(Edge-Triggered) ๋ฐ Non-Blocking ์ค์
// ๋ณํ๊ฐ ์ผ์ด๋๋ '์๊ฐ'์๋ง ํต์ง๋ฐ์ ์์คํ
์ฝ ํธ์ถ ํ์๋ฅผ ์ต์ํํฉ๋๋ค.
set_nonblocking(server_fd);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = server_fd;
// 3. ๊ด์ฌ ๋ฆฌ์คํธ ๋ฑ๋ก (epoll_ctl)
// ์ปค๋ ๋ด๋ถ ํธ๋ฆฌ ๊ตฌ์กฐ์ ์์ผ์ ๋ฑ๋กํฉ๋๋ค. ์ดํ ์์ผ ์ํ ๋ณ๊ฒฝ์
// ์ปค๋์ด ์ง์ ๊ด๋ฆฌํ๋ฏ๋ก ๋งค๋ฒ ์ ์ฒด ๋ฆฌ์คํธ๋ฅผ ์ ๋ฌํ ํ์๊ฐ ์์ต๋๋ค.
epoll_ctl(epfd, EPOLL_CTL_ADD, server_fd, &ev);
while (1) {
/**
* 4. ์ด๋ฒคํธ ๋๊ธฐ (epoll_wait)
* ํ๋ก์ธ์ค๋ Ready List์ ๋ฐ์ดํฐ๊ฐ ์ฐฐ ๋๊น์ง ํจ์จ์ ์ผ๋ก ๋๊ธฐํฉ๋๋ค.
* CPU๋ ์ด ๊ธฐ๊ฐ ๋์ ๋ค๋ฅธ ํ๋ก์ธ์ค๋ฅผ ์ฒ๋ฆฌํ ์ ์์ผ๋ฉฐ,
* Ready List์ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์ค๋ ์๊ฐ $O(1)$์ ์๋๋ก ์ฆ์ ๊นจ์ด๋ฉ๋๋ค.
*/
int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (int n = 0; n < nfds; ++n) {
if (events[n].data.fd == server_fd) {
// ์๋ก์ด ์ฐ๊ฒฐ ์๋ฝ ๋ก์ง
accept_new_connection(epfd, server_fd);
} else {
// ๋ฐ์ดํฐ ์ฝ๊ธฐ ๋ฐ ๋น์ฆ๋์ค ๋ก์ง ์ํ
handle_client_data(events[n].data.fd);
}
}
}
}
epoll์ด ๋ฌ์ฑํ ๊ธฐ์ ์ ๋์ฝ
epoll์ ๋จ์ํ ์๋๋ฅผ ๋์ธ ๊ฒ์ด ์๋๋ผ, ์ ์ ์คํ์ด์ค์ ์ปค๋ ์คํ์ด์ค ์ฌ์ด์ โ๋ถํ์ํ ๋ํโ๋ฅผ ์ ๊ฑฐํ์ต๋๋ค. ํ๋ก์ธ์ค ์ปจํ ์คํธ ์ค์์นญ์ ๋น์ผ ๋น์ฉ์ ์น๋ฅด๋๋ฐ,epoll์ ์์ผ ์ํ๋ฅผ ํ์ธํ๊ธฐ ์ํ ์ค์์นญ ํ์์ ๋ฐ์ดํฐ ๋ณต์ฌ๋์ ์ต์ํํจ์ผ๋ก์จ ํ๋์จ์ด ์ฑ๋ฅ์ ์ํํธ์จ์ด ์์ค์์ ์จ์ ํ ๋๋ฆด ์ ์๊ฒ ๋ง๋ค์์ต๋๋ค.
Java NIO
Java ์์ง๋์ด์๊ฒ Linux์ epoll์ ๊ฐ๋ ฅํ์ง๋ง ๋ค๋ฃจ๊ธฐ ๊น๋ค๋ก์ด ์์ ๋๊ตฌ์ ๊ฐ์ต๋๋ค. Java NIO(New I/O)๋ ์ด ๊ฑฐ์น ์ปค๋์ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ์ฒด์งํฅ์ ์ธ๊ณ๋ก ๋์ด์ฌ๋ ค, ๋จ์ผ ์ค๋ ๋๊ฐ ์์ฒ ๊ฐ์ ์ฐ๊ฒฐ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ Selector, Channel, Buffer๋ผ๋ ์ผ๊ฐ ํธ๋์ ์ถ์ํ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด์์ฒด์ ๋ ํ๋์จ์ด ์์์ ์ถ์ํํ์ฌ ์ ๊ณตํ๋ฉฐ, Java NIO๋ ๋ฐ๋ก ์ด ์ง์ ์์ ์ปค๋์ ์ฑ๋ฅ์ ์๋ฐ ๊ฐ์ ๋จธ์ (JVM) ์์์ ์จ์ ํ ๊ตฌํํด๋
๋๋ค.
Java NIO์ ์ ์๋ Selector์ ์์ต๋๋ค. ์ด๋ Linux epoll์ ์๋ฐํ ๋ํผ(Wrapper)๋ก, ์๋ง์ Channel๋ค ์ค I/O ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๊ฒ๋ค๋ง ๊ณจ๋ผ๋ด๋ ๋ฉํฐํ๋ ์ ์ญํ ์ ์ํํฉ๋๋ค. ๊ณผ๊ฑฐ Blocking I/O ๋ฐฉ์์ด โ์ฐ๊ฒฐ๋น ์ค๋ ๋ ํ๋โ๋ฅผ ์๋ชจํ๋ฉฐ ์ปจํ
์คํธ ์ค์์นญ ๋น์ฉ๊ณผ ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ๋ค๋ฉด, NIO๋ ๋จ ํ๋์ ์ค๋ ๋๋ง์ผ๋ก ์๋ง ๊ฐ์ ์์ผ์ ๊ฐ์ํฉ๋๋ค.
๋ฐ์ดํฐ์ ์ด๋ ์ญ์ ํ์ ์ ์ ๋๋ค. Java NIO๋ Direct Buffer๋ฅผ ํตํด โZero-copyโ์ ๊ฐ๊น์ด ์ฑ๋ฅ์ ๊ตฌํํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ ํ๋์จ์ด์์ ์ปค๋ ๋ฒํผ๋ก, ๋ค์ JVM ํ ๋ฉ๋ชจ๋ฆฌ๋ก ๋ณต์ฌ๋๋ ๊ณผ์ ์ ๊ฑฐ์น์ง๋ง, Direct Buffer๋ JVM ํ์ ๊ฑฐ์น์ง ์๊ณ ์ปค๋ ๋ฉ๋ชจ๋ฆฌ์ ์ง์ ์ํตํฉ๋๋ค. CPU์ RAM ์ฌ์ด์ ๋ง๋๋ณด๋ ํต๋ก๋ฅผ ๊ฐ์ฅ ์งง์ ๊ฒฝ๋ก๋ก ํ์ฉํ๋ ๊ฒ์ ๋๋ค.
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
/**
* Java NIO Selector๋ฅผ ์ด์ฉํ ๋น์ฐจ๋จ ์๋ฒ ๋ฃจํ
* * Java NIO๋ Linux์ epoll๊ณผ ๊ฐ์ ์ ์์ค ์ปค๋ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ์ฒด์งํฅ์ ์ผ๋ก ์ถ์ํํฉ๋๋ค.
* ์ด๋ ๋จ์ผ ์ค๋ ๋๊ฐ ์์ฒ ๊ฐ์ ํ๋ก์ธ์ค/์ค๋ ๋๋ฅผ ๋์ ํ์ฌ
* ์์์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ฒ ํ๋ '๋ฉํฐํ๋ ์ฑ'์ ์ ์์
๋๋ค.
*/
public class NioServer {
public void startServer() throws IOException {
// 1. Selector ๋ฐ ServerSocketChannel ์คํ
// Selector๋ ์ปค๋์ epoll ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌํ๋ ์๋ฐ ์ธก ๋๋ฆฌ์ธ์
๋๋ค.
Selector selector = Selector.open();
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.bind(new InetSocketAddress("localhost", 8080));
// 2. ๋น์ฐจ๋จ(Non-blocking) ์ค์
// ์ด ์ค์ ์ด ์์ด์ผ๋ง Selector๊ฐ ์ฌ๋ฌ ์ฑ๋์ ๋์์ ๊ฐ์ํ ์ ์์ต๋๋ค.
serverSocket.configureBlocking(false);
// 3. ๊ด์ฌ ์ด๋ฒคํธ ๋ฑ๋ก (ACCEPT)
// ์ปค๋์ ๊ด์ฌ ๋ฆฌ์คํธ(Red-Black Tree)์ ์ด ์๋ฒ ์์ผ์ ๋ฑ๋กํ๋ ๊ณผ์ ์
๋๋ค.
serverSocket.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO ์๋ฒ๊ฐ ์์๋์์ต๋๋ค. ์ด๋ฒคํธ๋ฅผ ๊ฐ์ํฉ๋๋ค...");
while (true) {
/**
* 4. ์ด๋ฒคํธ ๊ฐ์ (select)
* ์ด ์ง์ ์์ ์ค๋ ๋๋ Ready List์ ์ ํธ๊ฐ ์ฌ ๋๊น์ง ๋๊ธฐํ๋ฉฐ CPU ์์์ ๋ฐ๋ฉํฉ๋๋ค.
*/
selector.select();
// 5. ๋ฐ์ํ ์ด๋ฒคํธ(SelectionKey) ์ธํธ ํ๋
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
if (key.isAcceptable()) {
// ์ ๊ท ์ฐ๊ฒฐ ์๋ฝ ๋ฐ ๋น์ฐจ๋จ ๋ฑ๋ก
registerClient(selector, serverSocket);
} else if (key.isReadable()) {
// ๋ฐ์ดํฐ ์ฝ๊ธฐ ์ํ
// Direct Buffer ๋ฑ์ ์ฌ์ฉํ๋ฉด
// ์ ์ /์ปค๋ ์ฌ์ด์ ๋ฐ์ดํฐ ๋ณต์ฌ ๋น์ฉ์ 'Zero-copy'์ ๊ฐ๊น๊ฒ ์ค์ผ ์ ์์ต๋๋ค.
readData(key);
}
iter.remove(); // ์ฒ๋ฆฌํ ์ด๋ฒคํธ๋ ๋ช
์์ ์ผ๋ก ์ ๊ฑฐ
}
}
}
private void registerClient(Selector selector, ServerSocketChannel serverSocket) throws IOException {
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
private void readData(SelectionKey key) throws IOException {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = client.read(buffer);
if (bytesRead == -1) {
client.close();
} else {
// ๊ณ ํธ๋ํฝ ํ๊ฒฝ์์๋ ์ด ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ๋ณ๋์ ์์ปค ์ค๋ ๋ ํ๋ก ๋๊ฒจ
// Selector ์ค๋ ๋์ ์ง์ฐ์ ๋ฐฉ์งํ๋ ๊ฒ์ด ๊ณ ์ฑ๋ฅ ์ํคํ
์ฒ์ ์ ์์
๋๋ค.
buffer.flip();
System.out.println("๋ฐ์ดํฐ ์์ : " + new String(buffer.array()).trim());
}
}
}
๊ณ ์ฑ๋ฅ ์ถ์ํ ์ด๋ฉด์ ์จ๊ฒจ์ง ์ ์ด์ ๋ณต์ก์ฑ
Java NIO๋ ์ฑ๋ฅ ๋ฉด์์ ์๋์ ์ด์ง๋ง, ๋ฒํผ์
flip(),clear()์ฒ๋ฆฌ๋ ์์ผ์ ์ํ ๊ด๋ฆฌ ๋ฑ ๊ฐ๋ฐ์๊ฐ ์ ๊ฒฝ ์จ์ผ ํ ์ ์์ค์ ๋ณต์ก๋๊ฐ ๋งค์ฐ ๋์ต๋๋ค. ์ด๋ฌํ ์ด์ ๋ก ์ค์ ํ์ ์์๋ NIO๋ฅผ ์ง์ ๋ค๋ฃจ๊ธฐ๋ณด๋ค, ์ด๋ฅผ ํ ๋จ๊ณ ๋ ์ฐ์ํ๊ฒ ๊ฐ์ธ ์์ Netty ๊ฐ์ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ์ฌ Reactor ํจํด์ ๊ตฌํํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค. ๊ฒฐ๊ตญ ๊ธฐ์ ์ ์ ํ์ โ์ฑ๋ฅ ํ๋ณดโ์ โ์ ์ง๋ณด์ ์์ฐ์ฑโ ์ฌ์ด์์ ์ต์ ์ ๊ท ํ์ ์ ์ฐพ์๋ด๋ ๊ณผ์ ์ ๋๋ค.
Summary
I/O ๋ชจ๋ธ์ ํ๋ ๊ณ ์ฑ๋ฅ ์์คํ
์ํคํ
์ฒ๋ฅผ ์งํฑํ๋ ๊ฐ์ฅ ๊ทผ๋ณธ์ ์ธ ๊ธฐ๋ฅ์
๋๋ค. Blocking์ ์ง๊ด์ฑ์์ ์์ํด Non-Blocking์ ์์ ๋ฅผ ๊ฑฐ์ณ, ๋ฆฌ๋
์ค epoll๊ณผ Java NIO๋ผ๋ ๊ฑฐ๋ํ ์ฑ๋ฅ ์ต์ ํ์ ์ ์ ์ ์ด๋ฅด๊ธฐ๊น์ง ์์ง๋์ด๋ ๋์์์ด CPU ์ ํด ์๊ฐ์ ์ค์ด๊ณ ์์ ํ์ฉ๋๋ฅผ ๋์ด๋ ํฌ์์ ์ด์ด์์ต๋๋ค. ์ฑ๋ฅ์ ์๊ณ์ ์ ๊ฒฐ๊ตญ ์ปค๋๊ณผ ์ ์ ์คํ์ด์ค ์ฌ์ด์ ๋ฐ์ดํฐ ํ๋ฆ๊ณผ ๋ฌธ๋งฅ ์ ํ ๋น์ฉ์ ์ผ๋ง๋ ์ ๊ตํ๊ฒ ํต์ ํ๋๋์ ๋ฌ๋ ค ์์ต๋๋ค.





