Linux Kernel(4.14) Hacks

rousalome.egloos.com

포토로그 Kernel Crash




[라즈베리파이] 시스템 콜 테이블이란 [라즈베리파이] 시스템 콜

시스템 콜 테이블을 알아보기 전 POSIX 규약에 대해서 점검합시다.
POSIX(Portable Operating System Interface)란 응용 어플리케이션이 다양한 유닉스 계열 운영체제에서 호환성을 유지하면서 실행할 수 있게 만든 표준 규약입니다. 대표적인 POSIX 규약은 리눅스 저수준 함수, 시스템 콜 테이블, 프로세스 통신용으로 쓰는 시그널 번호입니다. 응용 어플리케이션은 각자 알고리즘과 구현 시나리오에 집중하고 리눅스 저수준 함수 세부 구현 내역과 리눅스 커널 동작에 신경을 쓸 필요가 없습니다.

리눅스 POSIX 표준으로 시스템콜 번호와 핸들러는 지정되어 있습니다. 시스템콜 테이블은 시스템콜 번호를 인덱스로 시스템 콜 핸들러를 분기시키는 역할을 수행합니다.

시스템 콜 테이블은 시스템 콜 번호와 시스템 콜 핸들러 함수 주소로 구성되어 있습니다.
번호 시스템 콜 핸들러 함수 위치
1 sys_exit kernel/exit.c
2 sys_fork kernel/fork.c
3 sys_read fs/read_write.c
4 sys_write fs/read_write.c
5 sys_open fs/open.c
6 sys_close fs/open.c
7 compat_sys_epoll_pwait kernel/sys_ni.c
8 sys_creat fs/open.c
9 sys_link fs/namei.c
10 sys_unlink fs/namei.c
11 sys_execve fs/exec.c
12 sys_chdir fs/open.c

위와 같은 시스템 콜 번호와 시스템 콜 핸들러 함수 목록은 POSIX 규약에 명시되어 있습니다. 따라서 리눅스 커널은 POSIX 규약에 명시된 시스템 콜 테이블에 따라 시스템 콜 세부 코드를 구현합니다.
32비트 계열 아키텍처와 64비트 아키텍처별로 시스템 콜 테이블이 다릅니다. 위 테이블은 Aarch32, 32 비트 계열 ARM 아키텍처에서 처리하는 시스템 콜 테이블입니다. 참고로 라즈베리파이는 Aarch32, 32 비트 계열 ARM 아키텍처에서 구동합니다.

유저 모드에서 R7 레지스터에 시스템 콜 번호를 지정한 다음 소프트웨어 인터럽트를 발생하고, 커널 모드로 vector_swi 벡터로 실행이 바뀌면 R7에 저장된 시스템콜 번호에 따라 시스템콜 번호를 분기시켜줍니다. 

리눅스 커널에서는 어떤 전역 변수가 시스템콜 테이블일까요? sys_call_table 이란 전역 변수가 시스템콜 테이블입니다. Trace32로 본 시스템콜 테이블은 다음과 같습니다.
d.v %y.l sys_call_table
________address|value_______|symbol
    NSD:80107FC4|0x8012D4E0   \\vmlinux\kernel/signal\sys_restart_syscall
1   NSD:80107FC8|0x80121E08   \\vmlinux\exit\sys_exit
2   NSD:80107FCC|0x8011C6D0   \\vmlinux\fork\sys_fork
3   NSD:80107FD0|0x802844FC   \\vmlinux\read_write\sys_read
4   NSD:80107FD4|0x8028459C   \\vmlinux\read_write\sys_write
5   NSD:80107FD8|0x80281788   \\vmlinux\open\sys_open
6   NSD:80107FDC|0x80280380   \\vmlinux\open\sys_close

32비트 아키텍처에서는 4바이트 단위로 심볼에 주소를 처리합니다. 따라서 함수 주소 길이는 4바이트입니다. 4바이트 단위로 시스템 콜 핸들러 함수 주소를 sys_call_table 주소에 저장하는 것입니다.

가장 왼쪽에 보이는 숫자가 시스템콜 번호이고 가장 왼쪽에 보이는 함수 이름이 시스템 콜 핸들러입니다. 시스템콜 번호 3번에 해당하는 시스템콜 핸들러는 sys_read() 함수 4번에 대응하는 핸들러는 sys_write() 함수입니다.

리눅스 저수준 함수 이름이 abc이면 이에 대응하는 시스템 콜 핸들러 함수 이름은 대부분 sys_abc() 입니다. 이 기준으로 유저 공간에서 read() 함수를 호출하면 소프트웨어 인터럽트가 발생한 후 시스템 콜 테이블을 통해 sys_read() 함수로 분기합니다.

다음에 유저 영역에서 시스템 콜 실행 직전 어떤 흐름으로 시스템 콜 번호를 지정하는지 어셈블리 코드 분석으로 상세히 살펴봅니다.

#Reference 시스템 콜


Reference(워크큐)
워크큐(Workqueue) Overview

.

핑백

덧글

댓글 입력 영역