CPU는 컴퓨터의 모든 것을 직접적으로 가동하는 뇌🧠이다.
주된 역할은 명령어를 실행하는 것인데, 명령어들이 늘 차례대로 존재하는 것은 아니다.
이를 위해 CPU 내부에는 프로그램 카운터(PC) 라는 레지스터가 존재한다.
PC는 다음에 실행할 명령어의 메모리 주소를 저장하고 있으며,
CPU는 기본적으로 명령어를 점진적으로, 즉 순차적으로 실행한다고 가정한다.
하지만 실제로는 명령어들이 순서대로 실행되지 않는 경우도 자주 발생한다.
이 경우 컴퓨터는 잠시 하던 일을 멈추고 급한일을 먼저 처리해야 한다.
이처럼 일반적인 흐름을 벗어나 예외적으로 흐름이 변경되는 현상을
이라고 한다.
예외적인 제어흐름은 컴퓨터 시스템의 모든 수준에서 발생한다.
컴퓨터시스템은 크게 세가지 계층으로 나눌 수 있다.
예를 들어,
하지만 현실에서는 각 계층이 긴밀하게 연결되어 협력하기 때문에,
어떤 계층에서 예외가 발생했는지 명확히 구분하기 어려운 경우도 많다.
💡 이벤트(event)
컴퓨터 안팎에서 발생한 변화나 요청을 알리는 신호로,
운영체제나 CPU가 특정 처리를 시작하게 만든다.
컴퓨터는 다양한 예외 상황을 미리 가정하고, 각 상황에 맞는 처리 방법(핸들러)을 준비해 놓는다.
각 예외 상황에는 고유한 번호가 부여되며, 이 번호에 따라 적절한 예외 처리 함수(핸들러) 가 실행된다.
예외가 발생하면, CPU는 예외 테이블(exception table) 이라고 불리는
점프 테이블(jump table) 을 통해 해당 핸들러를 찾아 호출한다.
이러한 방식은 간접 프로시저 호출(Indirect Procedure Call)이라고 한다.
간접 프로시저 콜이란?
보통 우리가 함수를 부를 때는,print_hello();처럼 함수 이름을 직접 적어서 호출한다.
그런데 간접 호출은 이렇게 직접 이름을 부르는 게 아니라,
"주소를 따라가서 호출" 하는 방식이다.쉽게 말해,
"어떤 상황이 생기면 이 주소에 있는 함수를 실행해줘!"
라고 미리 정해두고, 그 주소를 나중에 따라가서 함수를 실행하는 거다.
예외테이블은 다음과 같이 생겼다.
테이블의 왼쪽 숫자는 각각의 예외 상황에 부여된 고유 번호이며, 테이블에서의 인덱스이다.
우리는 이를 흔히 엔트리 k 라고 부른다.
가상 메모리에서의 주소 처럼,
엔트리 k = "가상번호" 로 이해하면 쉽다. 실제 주소를 따로 계산해주어야한다.
예외 테이블의 동작 방식을 살펴보자.
예외 테이블(exception table)은 실제로는 메모리에 저장된 배열처럼 동작한다.
각 엔트리는 8바이트(64비트) 크기의 핸들러 주소를 저장하고 있다.
즉, k번째 예외 번호에 해당하는 엔트리의 주소는 다음과 같이 계산된다.
주소 = 예외테이블의 시작 주소 + ( k × 8)
(여기서 8은 각 엔트리의 크기(8바이트)를 의미한다.)
이제 우리는 "왜 흐름이 바뀌는가?"를 이해했으니,
이후엔 실제로 흐름을 바꾸는 기술들 인터럽트, 예외, 프로세스 컨텍스트 스위칭, 시그널 처리 등을 하나씩 파고들 예정이다.🐭