reference:
- "리눅스 커널 내부구조" / 백승재, 최종무
- "Operating Systems: Three Easy Pieces" / Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau
사용자 수준 응용 프로그램에게 커널이 자신의 서비스를 제공하는 인터페이스이다. 따라서 사용자가 운영체제의 기능이나 모듈을 활용하기 위해서는 반드시 시스템 콜을 사용해야 한다. 따라서 시스템 콜은 커널로의 진입점(entry point)라고 볼 수 있다.
대표적인 예로는 새로운 태스크를 생성하는 sys_fork(), 파일의 내용을 읽는 sys_read(), 현재 실행중인 태스크의 실행 우선순위를 제어하는 sys_nice() 등이 있다.
리눅스 커널은 각 시스템 콜을 함수(시스템 콜 핸들러)로 구현해 놓고 각 시스템 콜이 요청되었을 때 대응되는 함수(시스템 콜 핸들러)를 호출하여 서비스를 제공
한다.
시스템 콜 핸들러 위치
예를 들어 sys_fork()는 ~/kernel/fork.c 파일에 구현되어 있으며, sys_read()는 fs/read_write.c 파일에 구현되어 있다.
시스템 콜 처리과정
위 그림을 통해 시스템 콜 처리과정을 볼 수 있다.
사용자 수준 응용이 fork()라는 시스템 콜을 요청했다고 가정한다. 그럼 /usr/lib/libc.a 라는 이름의 표준 C 라이브러리에 구현되어 있는 fork()라는 이름의 라이브러리 함수가 호출된다. 이 함수는 사용자 대신 트랩을 요청하는 일종의 대리인(agent)이자 시스템 콜 래퍼라 볼 수 있다. 이 라이브러리 함수는 CPU내의 범용 레지스터인 eax 레지스터에 fork() 함수에 할당되어 있는 고유한 번호인 2를 넣고, 0x80을인자로 트랩을 건다. 인텔 CPU에서 트랩을 거는 명령은 "int"이다. 일단 트랩이 걸리면 제어가 커널로 넘겨지고 CPU의 수행 모드가 사용자 수준에서 커널 수준으로 변화된다. 그리고 커널은 실행중이던 태스크의 문맥을 저장하고 트랩의 번호에 대응되는 엔트리에 등록되어 있는 함수를 호출한다. 지금 이 설명에서 트랩 번호는 0x80이며 따라서 호출되는 함수는 system_call()이다. 이 함수는 eax값(2)을 인덱스로 sys_call_table을 탐색한다. 그리고 최종적으로 sys_fork()라는 함수의 포인터를 얻어 fork 기능을 수행할 수 있다.