공부 자료: 📖 리눅스커널 내부구조
주변 장치와 커널이 통신하는 방식 중 하나로, 주변 장치나 CPU가 자신에게 발생한 사건을 리눅스 커널에게 알리는 매커니즘. e.g. 네트워크 패킷 도착시, 키보드가 눌릴 시 등.
인터럽트가 발생되면 문맥을 저장
하고 운영체제의 인터럽트 핸들러
를 통해 적절한 작업을 처리한 후 문맥을 복원
하게 된다.
모든 CPU는 인터럽트가 발생하면 PC 값을 정해진 특정 주소(ARM의 경우 특정 수조+offset)로 변경하도록 정해짐. 이 offset은 인터럽트의 종류에 따라 결정됨
각 주소에는 인터럽트 핸들러(= pintOS의 syscall_handler 함수)가 각 인터럽트의 종류에 맞게 실행해야 하는 특정 인터럽트 핸들러(syscall_exec 같은)로 분기(점프)하는 명령어를 기록해 둔다. 이렇게 특정 핸들러로 분기하는 것을 기록해둔 것을 IDT(interrupt descriptor table)
, IVT(interrupt vector table)
이라 부른다.
인터럽트를 처리한 후 다시 기존 문맥의 어디서부터 실행할지에 대한 여부는 시스템 콜마다 다를 것 (가령 페이지 폴트가 발생한 경우, 이를 페이지 테이블에 올린 후 다시 페이지 폴트가 발생한 그 명령어부터 시행해야 할 것이고, 시스템콜 같은 경우는 시스템 콜을 처리한 후 그 다음 주소부터 다시 시행할 것) 그래서 다시 원래 문맥으로 돌아올 때의 사용하는 함수가 인터럽트마다 다르다.
시스템 호출은 커널로의 진입점(entry point)을 의미한다.
핀토스로 예를 들면, 사용자가 사용하는 exec()
함수는 사용자 대신 트랩을 요청하는 일종의 대리인(agent)이고, 이 함수를 통해 트랩(인터럽트)를 걸게 됨 (인터럽트가 발생했을 때 이동하는 특정 주소 즉 idt를 참조할 수 있는 주소로 가게 됨)
int
exec (const char *file) {
return (pid_t) syscall1 (SYS_EXEC, file);
}
트랩이 걸리면 CPU의 수행모드가 사용자 수준에서 커널 수준으로 변화하고, 커널은 현재 실행 중이던 문맥을 저장한 후, 해당하는 시스템 콜 처리 함수를 호출한다.