시스템 콜 오버헤드 (System Call Overhead)

핵심 인사이트 (3줄 요약)

  1. 본질: 시스템 콜 (System Call)은 일반 응용 프로그램(User Mode)이 파일 읽기, 네트워크 통신, 메모리 할당 등 하드웨어 접근이 필요한 특권 작업을 운영체제 커널(Kernel Mode)에게 '대신해달라고 부탁하는' 유일한 합법적 소프트웨어 트랩(Trap) 통로다.
  2. 가치: 이 엄격한 문지기 시스템 덕분에 악성 코드나 버그 난 프로그램이 하드웨어를 직접 건드려 컴퓨터 전체를 망가뜨리는 사태를 완벽히 차단하는 철통 보안(Protection)을 제공한다.
  3. 융합: 하지만 이 부탁을 위해 '모드 전환(User $\rightarrow$ Kernel)'과 레지스터 검증 등을 거치는 과정에서 막대한 시간적 낭비(Overhead)가 발생한다. 현대 OS는 이 오버헤드를 우회하기 위해 eBPF, io_uring, DPDK 같은 커널 바이패스(Kernel Bypass) 아키텍처로 진화하고 있다.

Ⅰ. 개요 및 필요성 (Context & Necessity)

  • 개념:

    • 응용 프로그램은 하드웨어 자원(디스크, 랜카드)에 직접 접근할 권한이 없다.
    • 따라서 프로그램 내에서 파일에 글씨를 쓰거나(write), 다른 프로그램과 통신(send)을 하려면 반드시 운영체제 커널에 내장된 약속된 함수(System Call API)를 호출하여 커널로 진입해야 한다.
    • 이 진입과 탈출 과정에서 소비되는 부가적인 CPU 사이클 낭비를 시스템 콜 오버헤드라 부른다.
  • 필요성(문제의식):

    • 과거 MS-DOS 같은 구형 OS는 이런 장벽이 없어서 게임 프로그램이 비디오 카드 메모리에 직접 값을 썼다. 그러다 게임 코딩 실수 하나로 컴퓨터 전원이 나가거나 파란 화면(블루스크린)이 떴다.
    • 해결책: "어떤 프로그램도 하드웨어에 손대지 마라! 오직 전지전능한 '커널'만이 하드웨어를 만질 수 있는 **듀얼 모드(Dual Mode)**를 하드웨어(CPU) 수준에서 강제하자!"
  • 💡 비유:

    • 일반인(User Mode)이 구청에서 주민등록등본 원본(하드웨어 자원)을 직접 캐비닛에서 꺼내게 놔두면 원본이 찢어지거나 털릴 수 있다.
    • 그래서 반드시 두꺼운 유리벽 뒤에 있는 공무원(Kernel Mode)에게 신청서 양식(시스템 콜 번호)을 적어 창구(소프트웨어 인터럽트)로 제출해야 한다.
    • 이 과정에서 공무원이 신분증을 확인하고(권한 검증), 원본을 찾아서 복사본을 내어주기까지 **'기다리는 시간(오버헤드)'**이 발생한다.
  • 등장 배경:

    • CPU 제조사(인텔)가 보호 링(Ring 0 = 커널, Ring 3 = 유저)이라는 권한 분리 아키텍처를 도입하면서, 이 두 세계를 오가는 무거운 징검다리로서 int 0x80 또는 현대의 syscall 명령어가 탄생했다.
  ┌─────────────────────────────────────────────────────────────┐
  │                 듀얼 모드 (Dual Mode)와 시스템 콜의 경계선            │
  ├─────────────────────────────────────────────────────────────┤
  │                                                             │
  │   [ 유저 공간 (User Space) - Ring 3 ] - 권한 없음               │
  │     App: C언어 `printf("Hello");` 호출                        │
  │         │                                                   │
  │         ▼ 표준 라이브러리 (libc)                              │
  │         `write(fd, "Hello", 5)` 래퍼 함수 호출                 │
  │         │                                                   │
  │         ▼ CPU 레지스터에 시스템 콜 번호(예: 1번) 적재            │
  │ ─── Trap (소프트웨어 인터럽트: 0x80 또는 syscall 발생) ─────── ⚠️ 병목 │
  │         ▼  <--- 문맥 교환 (권한 상승, 보안 검증)                   │
  │                                                             │
  │   [ 커널 공간 (Kernel Space) - Ring 0 ] - 절대 권력            │
  │     OS: 시스템 콜 테이블(sys_call_table) 조회                 │
  │         │                                                   │
  │         ▼ 1번에 해당하는 `sys_write()` 함수 실행                │
  │     드라이버: 하드 디스크나 모니터 VRAM에 물리적 출력 수행           │
  │         │                                                   │
  │         ▼ 결과값(성공/실패)을 레지스터에 담고 복귀                  │
  │ ─── IRET (인터럽트 복귀 명령) ──────────────────────────────── ⚠️ 병목 │
  │         ▼  <--- 문맥 교환 (권한 강등, 원래 코드 복귀)              │
  │   유저 프로그램 마저 실행                                        │
  └─────────────────────────────────────────────────────────────┘

[다이어그램 해설] 이 그림은 단순히 함수 하나를 부르는 게 얼마나 거대한 벽을 넘는 일인지 보여준다. 같은 프로그램 안에서 a + b를 계산하는 함수 호출(Call)은 단 몇 클럭(나노초)이면 끝난다. 하지만 모니터에 글자를 띄우는 write 함수는 CPU의 하드웨어 특권 레벨을 뚫고 들어가는 인터럽트(Trap)를 발생시킨다. 이 붉은색 경계선(⚠️)을 넘을 때마다 CPU는 하던 일을 멈추고 보안 검증, 레지스터 백업, 모드 스위칭을 단행하며 수백~수천 클럭(마이크로초)을 소모한다. 즉, 시스템 콜은 일반 함수 호출보다 수십 배에서 수백 배 무거운 '초대형 통행료'를 지불하는 행위다.

  • 📢 섹션 요약 비유: 일반 직원이 옆자리 직원에게 펜을 빌려 달라고 말하는 것(일반 함수 호출)은 1초면 되지만, 사장님(커널) 금고에 있는 결재 도장을 쓰려면 복잡한 기안서를 올리고 비서실(Trap)의 승인을 거치는 데 하루(막대한 오버헤드)가 걸리는 시스템입니다.

Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)

오버헤드를 발생시키는 4대 근본 원인

시스템 콜을 불렀을 때 왜 느려지는지 커널 내부의 물리적/소프트웨어적 동작을 해부해 본다.

오버헤드 원인설명소비 비용 및 파괴력
1. 모드 스위치 (Mode Switch)하드웨어 링(Ring) 레벨이 3에서 0으로 승격되었다가 다시 3으로 강등됨. 보안 무결성 회로가 개입함.수십 나노초. (가장 기본적인 시간 지연)
2. 문맥 저장과 복원 (Context Save/Restore)유저 프로그램이 쓰던 CPU 레지스터 값(PC, SP, Flags 등)을 스택(Stack)에 백업하고, 커널용 스택을 새로 꺼내 세팅해야 함.수십~수백 나노초. 메모리 I/O 동반.
3. 매개변수 복사 (Copy from/to User)유저의 버퍼(char *buf) 주소를 커널이 바로 믿고 쓰면 해킹됨. 커널은 그 데이터를 안전한 커널 메모리 공간으로 **'물리적 복사(Copy)'**해 와서 검증한 뒤 사용.데이터 크기에 비례하여 수 마이크로초 소모. (가장 큰 병목)
4. 캐시와 파이프라인 오염 (Pollution)커널 코드가 실행되면서 기존 유저 프로그램이 따뜻하게 데워놓은 L1 명령어/데이터 캐시(Cache)와 CPU 분기 예측(Pipeline)이 통째로 쫓겨남.수십 마이크로초 지연. (눈에 안 보이지만 시스템 전체를 가장 느리게 만드는 악질 병목)

현대 하드웨어의 개선 (SYSENTER / SYSCALL 명령어)

과거 int 0x80 방식의 느린 속도를 개선하기 위해, 인텔과 AMD는 하드웨어 칩 레벨에서 직행 터널을 뚫었다.

  ┌───────────────────────────────────────────────────────────────────┐
  │                 Legacy Interrupt vs Fast System Call 비교         │
  ├───────────────────────────────────────────────────────────────────┤
  │                                                                   │
  │   [ 1세대: int 0x80 (전통적 소프트웨어 인터럽트) ]                    │
  │   App ──▶ CPU 인터럽트 핀 발생 ──▶ IVT(벡터 테이블) 탐색 ──▶ 권한 검사 │
  │       ──▶ 커널 스택 전환 ──▶ system_call 진입 (과정이 너무 길고 무거움)│
  │                                                                   │
  │   [ 2세대: syscall / sysenter (고속 직행로) ]                      │
  │   App ──▶ `syscall` 전용 어셈블리 명령어 실행                        │
  │       ──▶ CPU 내부의 특수 레지스터(MSR)에 미리 세팅된 주소로           │
  │           테이블 탐색 없이 단숨에 커널 진입점(Entry)으로 하드웨어 텔레포트!│
  │                                                                   │
  │   결과: CPU 사이클 낭비가 1/3로 줄어듦 (약 300 클럭 -> 100 클럭).       │
  │         하지만 여전히 "유저 데이터 복사"나 "캐시 오염" 문제는 남음.          │
  └───────────────────────────────────────────────────────────────────┘

[다이어그램 해설] 초창기 리눅스는 일반 하드웨어 에러(나눗셈 0 에러 등)를 처리하는 복잡한 인터럽트 테이블 게이트를 시스템 콜도 똑같이 탔다. 성능 하락을 참지 못한 하드웨어 제조사가 syscall이라는 단일 목적의 "슈퍼패스" 어셈블리 명령어를 CPU에 아예 박아버렸다. 이 명령어를 치면 CPU는 묻지도 따지지도 않고 MSR(Model Specific Register)에 저장된 커널 주소로 통제권과 스택을 즉시 스위칭한다. 덕분에 최신 OS에서는 시스템 콜의 '직접 비용'은 크게 줄었다. 그러나 근본적인 메모리 벽(Copy from user)은 그대로다.

  • 📢 섹션 요약 비유: 구청에 서류를 낼 때 긴 줄을 서서 1차 검문소를 거치던 방식(int 0x80)에서, 무인 제출 키오스크(syscall)를 도입해 제출 속도는 빨라졌습니다. 하지만 공무원이 뒷방에서 서류를 심사하는 복잡한 과정 자체(데이터 복사와 캐시 초기화)는 여전히 남아있습니다.

Ⅲ. 융합 비교 및 다각도 분석

API (라이브러리 함수) vs System Call의 명확한 차이

주니어 개발자들은 C언어의 printf나 파이썬의 print가 그대로 시스템 콜인 줄 착각한다.

비교 항목API (Application Programming Interface)System Call (시스템 콜)
실행 공간유저 모드 (Ring 3)커널 모드 (Ring 0)
비용 (Overhead)매우 저렴 (일반 함수 호출과 동일, 수 나노초)매우 비쌈 (모드 스위치, 검증 포함, 수백 나노초)
대표적인 예시printf(), malloc(), strcpy(), strlen()write(), sbrk(), mmap(), clone()
상호 관계래퍼(Wrapper). OS 이식성을 위해 API를 감싸 제공API 안에서 궁극적으로 하드웨어를 다룰 때만 은밀히 호출됨

※ 표준 라이브러리(libc)의 버퍼링 꼼수: printf를 1만 번 호출한다고 시스템 콜 write가 1만 번 불리지 않는다. C 라이브러리(API)는 유저 공간의 메모리에 글자들을 조용히 모아두었다가(Buffering), 버퍼가 꽉 차거나 개행문자(\n)를 만날 때만 단 1번 커널에 write() 시스템 콜을 날린다. 시스템 콜의 횟수를 줄이는 것이 성능 최적화의 1원칙이기 때문이다.

과목 융합 관점

  • 가상 메모리 (TLB / KPTI): 인텔 CPU의 스펙터/멜트다운(Meltdown) 보안 결함 사태 이후, 시스템 콜 오버헤드는 최악의 재앙을 맞았다. 커널 공간과 유저 공간의 페이지 테이블을 완전히 찢어버리는 KPTI (Kernel Page-Table Isolation) 패치가 적용되면서, 시스템 콜을 부를 때마다 페이지 테이블을 통째로 교체하고 TLB 캐시를 다 날려버려야 했다. 이로 인해 I/O 집약적 서버(DB, Redis)의 성능이 하루아침에 30% 폭락하는 초유의 사태가 있었다.

  • 분산 시스템 (MSA): 마이크로서비스 환경에서 수많은 REST API(HTTP) 통신은 내부적으로 무수한 소켓 read/write 시스템 콜을 유발한다. 이 통신 오버헤드를 견디다 못해 최근의 클라우드 네이티브 아키텍처는 유저 스페이스 내에서 바이패스 통신을 하거나 커널 레이어에서 바로 라우팅(eBPF)을 쳐버리는 서비스 메시(Service Mesh)로 진화 중이다.

  • 📢 섹션 요약 비유: 택배(시스템 콜)를 보낼 때마다 배송비(오버헤드)가 5천 원씩 드는데, 사탕 1개(1바이트) 팔릴 때마다 택배를 보내면(비효율적 로직) 회사가 망합니다. 큰 상자에 사탕을 100개 모았다가 한 번에 택배를 보내는 것(API 버퍼링)이 프로그래밍 최적화의 정석입니다.


Ⅳ. 실무 적용 및 기술사적 판단

실무 시나리오 및 최적화 아키텍처 (커널 바이패스)

  1. 시나리오 — Nginx 정적 파일(이미지, 동영상) 서빙 서버의 CPU 병목: 클라이언트가 1GB짜리 영상을 요청했다. 기존 방식으로 read() 로 디스크에서 커널로, 다시 커널에서 유저 공간 버퍼로 퍼 올린 뒤, 다시 write()로 유저에서 커널 네트워크 소켓 버퍼로 넘겨서 전송했다. 이 헛짓거리 탓에 10Gbps 대역폭을 다 쓰기도 전에 CPU 사용률이 100%를 치고 뻗었다.

    • 아키텍트 판단 (sendfile / Zero-copy): 디스크에 있는 파일을 유저가 굳이 눈으로 볼(조작할) 필요 없이 바로 네트워크로 쏴버려도 된다면, 유저 공간으로 가져오는 행위 자체가 사치다. 리눅스의 sendfile() 시스템 콜을 사용한다. 이 함수를 부르면 커널 내부 공간에서 디스크 버퍼 큐 $\rightarrow$ 네트워크 카드 큐로 직접 DMA(Direct Memory Access) 전송을 꽂아버린다. 유저-커널 복사 비용이 0이 되는 "Zero-copy" 마법으로 CPU 사용률을 5% 미만으로 떨어뜨린다.
  2. 시나리오 — 고빈도 트레이딩 및 패킷 스니핑 장비의 한계 돌파 (DPDK): 초당 1,000만 개의 미세한 네트워크 패킷(UDP)을 처리해야 하는 방화벽이나 금융 거래 장비를 만들고 있다. 소켓 recvfrom() 시스템 콜을 천만 번 부르면 커널 스위칭 오버헤드만으로 시스템이 녹아내린다.

    • 아키텍트 판단 (Kernel Bypass 적용): 운영체제의 시스템 콜과 커널 네트워크 스택을 100% 버린다. 인텔의 DPDK (Data Plane Development Kit) 프레임워크를 도입한다. 랜카드(NIC)의 메모리 주소를 유저 공간(User Space)의 앱 메모리에 mmap으로 직접 매핑하고, 앱이 무한 루프(Polling)를 돌며 랜카드에서 직접 패킷을 퍼올린다. 시스템 콜이 아예 0번 발생하므로, 마이크로초(µs) 단위의 극단적 초저지연을 달성한다.
  ┌───────────────────────────────────────────────────────────────────┐
  │                 시스템 콜 병목 회피를 위한 최신 아키텍처 (io_uring)         │
  ├───────────────────────────────────────────────────────────────────┤
  │                                                                   │
  │   [ 전통적 동기식 I/O ]                                              │
  │   App ──(read 시스템콜)──▶ 대기(Block) ──▶ 완료 후 ──(write)──▶ 대기 │
  │   ※ I/O 1건당 시스템 콜 1번 호출. 문맥 교환 폭탄.                         │
  │                                                                   │
  │   [ 차세대 비동기 I/O (리눅스 io_uring) ]                             │
  │                                                                   │
  │   유저 공간 (User)                 [ 공유 링 버퍼 (Shared Ring) ]  │
  │   ┌────────────┐   1. 명령어 투척   ┌──────────────────┐          │
  │   │ Application├───────────────▶│ SQ (Submission Q)│          │
  │   │ (논블로킹)   │                  └────────┬─────────┘          │
  │   └─────▲──────┘                           │                    │
  │           │      3. 결과 회수                ▼ 폴링 감지            │
  │           └───────────────────────┌──────────────────┐          │
  │                                   │ CQ (Completion Q)│          │
  │                                   └────────▲─────────┘          │
  │                                            │ 백그라운드 처리        │
  │   ─────────────────────────────────────────┼────────────────── │
  │   커널 공간 (Kernel)                       (OS 커널 워커 스레드)      │
  │                                                                   │
  │   ※ 결과: 유저 앱은 공유 메모리(큐)에 "파일 100개 읽어!"라고 메모리만 쓰고    │
  │      시스템 콜은 단 한 번도 안 부름! (Zero-Syscall). 극한의 성능 혁명.      │
  └───────────────────────────────────────────────────────────────────┘

[다이어그램 해설] 이것이 2020년대 이후 리눅스 백엔드 아키텍처를 뒤흔들고 있는 io_uring의 본질이다. 그동안 시스템 콜 횟수를 줄이려고 API 버퍼링 같은 소프트웨어 꼼수를 썼다면, 이제는 OS 자체가 "유저와 커널 사이에 아예 우체통(공유 링 버퍼)을 놔둘 테니, 문 두드리지(시스템 콜) 말고 거기 편지 넣어두면 커널이 알아서 수거해서 처리해 줄게"라고 선언한 것이다. 이로 인해 시스템 콜을 호출할 때 필연적으로 발생하던 권한 스위칭, 멜트다운 방어막(KPTI)의 오버헤드를 완벽하게 우회하면서도 보안을 유지하는 궁극의 타협점을 이뤄냈다.

안티패턴

  • for 루프 안의 System Call: 파일에서 1GB를 읽을 때, char c; for(1 to 10^9) read(fd, &c, 1); 처럼 1바이트 단위로 시스템 콜을 10억 번 날리는 코드. C 초보자들이 흔히 저지르는 이 재앙은 디스크 속도의 문제가 아니라 10억 번의 권한 스위칭 오버헤드 때문에 시스템이 수십 분간 멈추는(Hang) 현상을 부른다. 반드시 큰 버퍼(최소 4KB, 페이지 사이즈) 단위로 뭉텅이로 읽어야 한다.

  • 📢 섹션 요약 비유: 우물에서 물을 풀 때 작은 숟가락으로 만 번을 퍼 나르면(바이트 단위 시스템 콜) 허리가 부러집니다. 커다란 양동이(버퍼)로 한 번에 가득 퍼오는 것이, 내 몸(CPU 오버헤드)을 지키는 가장 현명한 노동 방식입니다.


Ⅴ. 기대효과 및 결론

정량/정성 기대효과

구분무지성 시스템 콜 남용 환경버퍼링 및 Kernel Bypass 적용 환경개선 효과
정량 (I/O 스루풋)초당 수만 패킷 처리 후 CPU 100% 마비초당 수천만 패킷 처리 (DPDK/io_uring)네트워크 및 스토리지 하드웨어 대역폭(Bandwidth) 100% 활용
정량 (컨텍스트 오버헤드)CPU 사이클의 40%가 sys(커널) 영역 점유sys 점유율 5% 미만으로 하락사용자의 비즈니스 로직(us)에 CPU 연산 자원 몰빵 가능
정성 (보안 유지)편의를 위해 루트 권한을 남발하여 위험 노출듀얼 모드 보호는 유지하되 통신 방식을 개선보안과 성능이라는 두 마리 토끼의 구조적 타협 완성

미래 전망

  • eBPF 커널 내 사용자 코드 실행: 시스템 콜을 부르는 횟수를 줄이는 걸 넘어, "아예 내가 짠 코드를 커널 안으로 밀어 넣어서 그 안에서 돌게 하면 어떨까?"라는 발상이 eBPF(Extended BPF)다. 커널을 재컴파일하지 않고도 안전한 샌드박스 형태로 유저의 C 프로그램 코드를 커널 네트워크 스택 한가운데 삽입하여 시스템 콜 장벽을 아예 없애버리는 기술이 클라우드 관측/보안 생태계(Cilium, Falco)를 장악하고 있다.
  • Unikernel (유니커널) 패러다임: 클라우드 가상 머신(VM) 하나에 딱 하나의 애플리케이션만 올린다면, 굳이 커널과 유저 모드를 나눌 필요가 있을까? 보안(격리)은 밑단의 하이퍼바이저가 해주므로, 앱과 커널(OS)을 하나의 단일 실행 파일(Single Address Space)로 컴파일해 버리는 유니커널은 듀얼 모드 자체를 삭제하여 시스템 콜 비용 0, 부팅 5 밀리초를 달성한 극단적인 미래형 마이크로서비스다.

참고 표준

  • POSIX API (Portable Operating System Interface): UNIX 계열 운영체제들이 제공해야 할 시스템 콜과 C 라이브러리의 규격을 정의한 IEEE 표준.
  • vDSO (Virtual Dynamically Shared Object): gettimeofday() 같이 단순히 시계만 확인하는 작업에 시스템 콜 문맥 교환을 태우는 것은 낭비이므로, 커널이 읽기 전용 시계 데이터를 유저 메모리에 맵핑(vDSO)해 주어 시스템 콜 없이 시간을 읽게 한 리눅스의 가속 표준 기술.

시스템 콜 오버헤드는 "성능과 보안의 영원한 줄다리기"를 상징하는 컴퓨터 공학의 원초적 병목이다. 70년대에는 권한을 분리하여 안정을 얻었으나, 나노초를 다투는 100Gbps 네트워크 시대가 오면서 이 무거운 성벽의 문지기를 거치는 과정 자체가 인프라 전체의 발목을 잡았다. 오늘날 시스템 아키텍트들의 가장 눈부신 혁신(mmap, sendfile, DPDK, io_uring, eBPF)은 모두 **"어떻게 하면 보안을 해치지 않으면서, 이 빌어먹을 시스템 콜의 높은 벽 아래로 몰래 지하 터널을 뚫어 데이터를 고속으로 빼낼 수 있을까?"**에 대한 치열한 대답들이다.

  • 📢 섹션 요약 비유: 철통 보안을 자랑하는 거대한 성문(시스템 콜)으로만 식량을 나르다 보니 성 안 사람들이 굶어 죽을 판이 되자, 성벽의 강도(보안)는 유지하면서 성벽 밑으로 물(데이터)만 통과할 수 있는 튼튼하고 안전한 지하 파이프(Kernel Bypass)를 설계해 낸 인프라 토목 공사의 진화입니다.

📌 관련 개념 맵 (Knowledge Graph)

개념 명칭관계 및 시너지 설명
듀얼 모드 (Dual Mode)시스템 콜이 존재하는 근본 이유로, 하드웨어 차원에서 User Mode와 Kernel Mode를 분리하여 시스템 보호막을 치는 구조다.
소프트웨어 인터럽트 (Trap)시스템 콜을 호출할 때 0x80이나 syscall 명령어를 통해 CPU를 고의로 중단시켜 커널 영역으로 유도하는 방아쇠 메커니즘이다.
문맥 교환 (Context Switch)시스템 콜 발생 시 필수적으로 수반되는 레지스터와 스택의 저장/복원 과정으로 가장 큰 직접 비용을 차지한다.
버퍼 캐시 / API 버퍼링시스템 콜 호출 횟수 자체를 극단적으로 줄이기 위해 응용 프로그램단(libc)에서 자잘한 데이터를 모아서 한 번에 쏘는 필수 최적화 기법이다.
Kernel Bypass (커널 우회)초고속 장비의 데이터를 처리하기 위해 아예 시스템 콜을 무시하고, 유저 프로그램이 하드웨어 메모리에 직접 붙는 DPDK 같은 최신 아키텍처다.

👶 어린이를 위한 3줄 비유 설명

  1. 컴퓨터 세상에는 일반 시민(프로그램)과 경찰 아저씨(운영체제 커널)가 살아요. 시민은 위험한 무기(하드웨어)를 절대 만질 수 없어요.
  2. 시민이 무기를 써야 할 일이 생기면 경찰서에 가서 서류를 쓰고 부탁해야 하는데, 이걸 '시스템 콜'이라고 해요. 서류 심사받느라 줄을 서야 해서 시간이 꽤 걸리죠(오버헤드).
  3. 줄을 너무 자주 서면 일을 못 하니까, 똑똑한 사람들은 부탁할 일 10개를 바구니에 모아뒀다가 한 번에 경찰서에 가거나(버퍼링), 아예 안전한 전용 파이프(io_uring)를 설치해서 일 처리를 짱 빠르게 만들었답니다!