1. 인터럽트 처리 과정
인터럽트
- 주변 장치와 커널이 통신하는 방식 중의 하나
- 주변 장치나 CPU가 자신에게 발생한 사건을 리눅스 커널에게 알리는 매커니즘
- 인터럽트가 발생하면 운영체제는 왜 인터럽트가 발생했는지 살펴보고 적절한 작업 처리 → 처리 함수 : 인터럽트 핸들러
인터럽트 종류
- 발생 원인에 따라 크게 2가지로 구분됨
- 외부 인터럽트
- 현재 수행중인 태스크와 고나련 없는 주변장치에서 발생된 비동기적인 하드웨어적인 사건 의미
- 트랩
- 현재 수행중인 태스크와 관련있는 즉, 동기적으로 발생하는 사건 의미
- 소프트웨어적인 사건
- 예외처리라고도 함
- ex) 0으로 나누는 연산, 세그멘테이션 결함, 페이지 결함 등
리눅스의 인터럽트 관리 기법
- 외부 인터럽트와 트랩을 동일한 방식으로 처리
- 인터럽트를 처리하기 위한 루틴을 함수로 구현해놓은 뒤, 각 함수의 시작 주소를 리눅스의 IDT인 idt_table이라는 이름의 배열에 기록
- 커널 내부구조 수정 없이 인터럽트를 처리하기 위해 idt_table의 0~31까지 32개의 엔트리를 CPU의 ‘트랩’ 핸들러를 위해 할당하고, 그 외의 엔트리는 ‘외부 인터럽트’의 핸들러를 위해 사용
- 외부에서 인터럽트를 발생시킬 수 있는 라인은 한정된 개수임 → 함부로 할당하거나 무조건 독점하여 사용하는 것은 매우 불합리함 ⇒ 외부 인터럽트를 위한 번호는 별도로 관리 (irq_desc 테이블)
커널이 인터럽트를 받으면 즉시 인터럽트 핸들러를 호출할 수 있는 것은 아님
호출 전 문맥 저장(context save)을 해야하며, 인터럽트 처리가 완료되면 저장된 문맥을 복원(context restore)해야 함
트랩
- 같은 트랩이라 할지라도 어떤 트랩이냐에 따라 구분할 필요 있음
- fault
- fault를 일으킨 명령어 주소를 eip에 넣어 두었다가 해당 핸들러가 종료되고 나면 eip에 저장되어 있는 주소부터 다시 수행 시작
- trap
- trap을 일으킨 명령어의 다음 주소를 eip에 넣어 두었다가 그 다음부터 다시 수행
- ex) 시스템 콜
- abort
- 심각한 에러인 경우 발생 → 현재 테스크를 강제 종료시킴
- eip값을 저장할 필요가 없음
2. 시스템 호출 처리 과정
시스템 호출
- 사용자 수준 응용 프로그램들에게 커널이 자신의 서비스를 제공하는 인터페이스
- 사용자가 운영체제의 기능이나 모듈을 활용하기 위해서는 반드시 시스템 호출을 사용해야 함 → 커널로의 진입점 (entry point)
- 리눅스에서 시스템 호출을 서비스 해주는 함수에는 전통적으로 sys_라는 접두사가 붙음
- 리눅스 커널은 각 시스템 호출을 함수로(시스템 호출 핸들러) 구현해 놓고 각 시스템 호출이 요청되었을 때 대응되는 함수를 호출하여 서비스 제공
3. 새로운 시스템 호출 구현
새로운 시스템 호출을 위한 커널 수정
- 리눅스 커널에서 각 시스템 호출마다 유일하다고 했던 시스템 호출 번호를 하나 새로 할당하고 해당 시스템 콜을 처리할 함수 지정
- 정상적인 컴파일을 위해 시스템 호출 테이블에 새로운 시스템 호출 함수 원형 등록
- 시스템 호출 처리 함수 구현
- 태스크 관리자와 관련된 함수 : kernel/ 디렉터리
- 파일시스템과 관련된 함수 : fs/ 디렉터리
- 커널 수준에서 수행되는 함수이므로 사용자 수준에서 수행되는 표준 C 라이브러리를 사용할 수 없음
- 커널 컴파일 수행
- make 명령이 컴파일 할 때 새로 등록한 파일도 컴파일 할 수 있도록 수정
- 리부팅
사용자 수준 응용 구현 - 라이브러리 이용 X
- 시스템 호출을 부르기 위해 syscall()이라는 매크로 사용
- 함수 이름을 직접 호출할 수 없음
사용자 수준 응용 구현 - 라이브러리 이용 O
- 라이브러리 : 사용자들이 자주 사용하는 함수들의 집합
- 함수 이름으로 호출하기 위해서는 라이브러리 필요
- “ar” 이라는 명령을 통해 라이브러리 생성
이 글은 아래의 책을 공부 및 정리한 내용입니다.
리눅스 커널 내부구조 - 예스24