ONE QUESTION AT A TIME.

천천히 생각하고, 분명하게.

TODAY’S QUESTION1391 / 1500
운영체제난이도 하5분 답변 목표 · 보강본

파일을 읽는 시스템 호출이 일반 함수 호출보다 비싸다고 합니다. 사용자 모드에서 커널로 들어갈 때 무엇이 달라지며 항상 다른 스레드로 전환되나요?

잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?

답변과 점검 포인트 펼치기답변 접기
01

구두 답변

정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.

일반 함수 호출은 보통 같은 프로세스의 사용자 모드에서 호출 규약에 따라 다른 코드로 분기합니다. 시스템 호출은 파일·소켓·프로세스 제어처럼 커널이 권한을 가진 기능을 요청하기 위해 정해진 진입점으로 들어가며, 커널은 인자와 포인터를 검증하고 필요한 권한을 확인한 뒤 결과를 돌려줍니다. 사용자 모드에서 커널 모드로 권한 수준이 바뀌는 것과 CPU가 다른 스레드로 넘어가는 것은 별개의 사건입니다. 이 차이가 시스템 호출 경계의 핵심입니다.

즉시 완료와 블로킹을 나눕니다

파일 데이터가 페이지 캐시에서 준비돼 있거나 장치가 즉시 응답하면 같은 스레드가 커널 코드를 수행하고 사용자 모드로 복귀할 수 있습니다. 반대로 데이터가 준비되지 않았거나 소켓 수신을 기다리면 현재 스레드는 sleep 상태가 되고 스케줄러가 다른 runnable 스레드를 선택할 수 있습니다. 이때 다른 스레드로 전환된 것은 시스템 호출의 정의가 아니라 블로킹 경로의 결과입니다. 한 시스템 호출이 여러 내부 작업이나 비동기 완료를 만들 수도 있으므로 syscall 횟수와 context-switch 횟수를 일대일로 세지 않겠습니다.

libc 함수 중에는 vDSO처럼 사용자 공간에서 커널의 시간 정보를 읽거나 단순한 래퍼로 끝나는 것도 있고, 버퍼가 있는 stdio처럼 여러 작은 요청을 하나의 syscall로 묶는 것도 있습니다. 반대로 작은 read·write를 반복하면 사용자-커널 진입·복귀, 권한 검사, 버퍼 복사와 캐시 비용이 누적됩니다. 버퍼링·벡터 I/O·배치는 진입 횟수를 줄일 수 있지만 데이터를 모으느라 첫 바이트 지연과 메모리 사용이 늘 수 있습니다.

호출 수가 아니라 병목을 확인합니다

strace 같은 호출 추적이나 플랫폼별 syscall 통계로 실제 커널 진입을 확인하고, 호출별 크기·소요 시간·블로킹 여부·복사량·page fault와 컨텍스트 스위치를 함께 기록합니다. 파일 읽기가 느리다면 syscall 경계 자체, 저장 장치, 페이지 캐시 miss, 애플리케이션의 작은 요청 중 무엇인지 분리해야 합니다. 비동기 API로 바꿔도 완료를 기다리는 방식이 블로킹이면 요청 스레드는 여전히 묶일 수 있으므로, 호출 경계와 작업 수명까지 함께 검증하겠습니다.

시스템 호출의 비용은 모드 전환만으로 정해지지 않습니다. 작은 read 1,000번은 각 진입·복귀와 복사 비용이 누적되지만, 1MiB 한 번으로 합치면 첫 바이트를 기다리는 시간과 버퍼 메모리가 늘 수 있습니다. 파일이 page cache에 있는지, 파일 시스템 잠금과 실제 장치 대기가 있는지에 따라 같은 호출의 비용도 달라집니다. 벡터 I/O나 배치는 호출 수를 줄여도 부분 완료와 버퍼 수명 계약을 추가합니다.

nonblocking syscall은 준비되지 않았다는 결과를 즉시 반환할 수 있지만 데이터 완료는 후속 readiness 이벤트 뒤에 일어납니다. 반대로 라이브러리 내부 worker thread가 blocking read를 대신하면 호출한 스레드는 안 막혀도 시스템 worker와 버퍼를 계속 점유합니다. 실제 syscall·대기 주체·복사량·bytes·context switch를 추적하고, 오류·취소·버퍼 재사용까지 포함한 end-to-end p99로 최적화를 판단하겠습니다.

호출 횟수와 호출 바이트를 함께 보아야 합니다. 4KiB를 1,000번 읽는 경로와 4MiB를 한 번 읽는 경로는 syscall 수는 다르지만 저장 장치와 복사 비용의 비중이 다를 수 있습니다. 배치 후에도 부분 완료·취소·버퍼 재사용 오류가 없는지 확인해 최적화의 부작용을 막겠습니다.

비동기 API가 호출한 스레드를 막지 않아도 내부 worker와 버퍼를 점유할 수 있습니다. nonblocking syscall은 준비되지 않았음을 즉시 반환할 뿐 데이터가 완료된 것이 아니며, 후속 readiness나 completion 경로가 필요합니다. 호출 수를 줄이는 최적화는 부분 완료·취소·버퍼 수명까지 포함해 검증하겠습니다.

02

득점 포인트

이해가 드러나는 지점을 확인해 보세요.

  • 권한 모드 전환과 다른 스레드로의 스케줄링을 구분한다.
  • 즉시 완료·블로킹·버퍼링 경로의 차이를 설명한다.
  • 호출 횟수·복사량·fault·실제 대기를 함께 측정한다.
03

감점 포인트

놓치기 쉬운 조건과 오해를 짚어 보세요.

  • 모든 syscall이 다른 스레드로 전환된다고 말한다.
  • 모든 libc 함수가 반드시 커널에 진입한다고 말한다.
  • syscall 횟수만 줄이면 지연이 해결된다고 단정한다.
04

더 파고들 거리

하나 더 질문하며 이해의 범위를 넓혀 보세요.

득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.

원리부터 공부하고 싶다면

답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.

← 전체 질문 보기