(서두 ~ “Finally, we discuss nonlocal jumps…”) — 장 도입부: ECF의 동기와 개요
- 제어 흐름(Control Flow): 전원이 켜진 순간부터 종료까지, PC는 명령어 주소 (a_0, a_1, …)의 연속을 따라가며, (a_k a_{k+1}) 전이는 control transfer라 부른다. 인접한 주소로의 “매끄러운” 흐름이 기본이지만, jumps, calls, returns가 이를 끊어 프로그램 상태 변화에 반응한다.
- 시스템 수준 변화: 내부 변수로 포착되지 않는 시스템 상태(타이머 인터럽트, 네트워크 패킷 도착, 디스크 I/O 완료, 자식 프로세스 종료 등)에도 반응해야 하며, 현대 시스템은 이를 위해 Exceptional Control Flow(ECF)—제어 흐름의 급격한 변화—를 사용한다.
- ECF의 계층적 발생:
- 하드웨어: 이벤트 → exception handlers로 급격한 제어 이동.
- 운영체제: context switch로 프로세스 간 제어 이양.
- 애플리케이션: signals로 핸들러에 제어 이양, nonlocal jumps로 스택 규율을 우회.
- 학습 필요성:
- OS의 I/O, 프로세스, 가상 메모리의 기본 메커니즘 이해,
- trap/system call을 통한 앱–OS 상호작용 이해,
- 프로세스 생성/대기, 알림, 처리 등 강력한 ECF API로 흥미로운 프로그램(예: 셸, 웹 서버) 작성,
- 동시성 이해의 출발점(예: 인터럽트, 프로세스/스레드 중첩, 시그널),
- 소프트웨어 예외(C++/Java의 try–catch–throw, C의 setjmp/longjmp)의 저수준 원리 이해.
- 장 구성 안내: **예외(exceptions)**와 시스템 콜(예외의 한 형태), 그리고 프로세스/시그널, 마지막으로 nonlocal jumps를 다룸.
8.1 Exceptions — 정의와 큰 그림
- 예외(exception): 프로세서 상태 변화(이벤트)에 반응한 제어 흐름의 급격한 전환.
- 동작 개요: 현재 명령어 (I_{}) 실행 중 이벤트 감지 → exception table(점프 테이블)을 통한 간접 프로시저 호출로 해당 exception handler 진입 → 처리 후 세 가지 중 하나:
- (I_{})로 복귀(현재 명령어 재시도),
- (I_{})로 복귀(다음 명령어 진행),
- 프로그램 abort.(위 반환 동작의 구체 차이는 8.1.2에서 분류별로 규정됨.)
8.1.1 Exception Handling — 하드웨어/소프트웨어의 역할 분담
- 예외 번호: 각 예외는 고유의 비음수 정수 번호를 가짐. 일부는 프로세서 설계자가(예: divide by zero, page fault, 메모리 접근 위반, breakpoint, overflow), 일부는 커널 설계자가(예: system call, 외부 I/O signals) 할당.
- 부팅 시: OS가 exception table을 초기화하고, 엔트리 k에 예외 k의 핸들러 주소 저장.
- 런타임: 이벤트 감지 → 예외 번호 k 결정 → exception table base register를 기준으로 엔트리 k를 인덱싱하여 해당 핸들러로 간접 호출.
- 프로시저 호출과의 유사/차이:
- 하드웨어가 반환 주소를 스택에 푸시(예외 종류에 따라 (I_{}) 또는 (I_{})).
- 재시작에 필요한 추가 프로세서 상태(예: x86-64의 EFLAGS)도 푸시.
- 유저→커널 전환 시 이 상태들은 커널 스택에 저장.
- 핸들러는 커널 모드로 실행(시스템 자원 전권).
- 종료: 핸들러는 필요 시 return-from-interrupt 특수 명령으로 상태 복원(필요하면 유저 모드로) 후 인터럽트된 프로그램에 복귀.
8.1.2 Classes of Exceptions — 네 가지 분류
- Interrupts(인터럽트):
- 비동기(특정 명령어와 무관). I/O 디바이스가 프로세서 인터럽트 핀 신호와 함께 예외 번호를 버스에 올림.
- 현재 명령어 완료 후 감지 → interrupt handler 호출 → 항상 (I_{})로 복귀. 프로그램은 “마치 없었던 듯” 계속 진행.
- Traps(트랩) & System Calls:
- 의도적 예외(명령어에 의해 유발). 항상 (I_{})로 복귀.
- 핵심 용도: user↔︎kernel 간 procedure-like 인터페이스, 즉 system call 제공. 유저 프로그램은 syscall n 같은 특수 명령으로 커널 서비스(예: read, fork, execve, exit)를 요청.
- Faults(폴트):
- 에러 조건이지만 복구 가능할 수 있음. 핸들러가 교정하면 faulting instruction 재실행((I_{})로 복귀). 복구 불가 시 커널의 abort 루틴으로 넘어가 프로그램 종료.
- 대표: page fault—해당 페이지를 디스크에서 메모리로 적재 후 명령을 재시도.
- Aborts(어보트):
- 치명적/비복구적 오류(주로 하드웨어 오류, 예: 메모리 비트 오류). 핸들러는 프로그램으로 복귀하지 않음, abort 루틴으로 종료 처리.