Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

8200
629
98815


[리눅스커널] 시스템 콜: 시스템 콜 테이블이란 11장. 시스템 콜

시스템 콜 테이블은 시스템 콜 번호와 시스템 콜 핸들러 함수 주소로 구성되어 있습니다.
시스템 콜 번호 시스템 콜 핸들러 함수 위치
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 규약에 명시된 시스템 콜 테이블에 따라 시스템 콜 세부 코드를 구현합니다.

 ARM 프로세서에서도 32비트 계열 아키텍처와 64비트 아키텍처별로 시스템 콜 테이블이 다릅니다. 위 테이블은 Aarch32, 32 비트 계열 ARM 아키텍처에서 처리하는 시스템 콜 테이블입니다. 참고로 라즈베리파이는 Aarch32, 32 비트 계열 ARMv7 아키텍처에서 구동됩니다.

유저 모드에서 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() 함수입니다. 

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

이번엔 위에서 잠시 언급한 POSIX 규약를 소개하겠습니다. POXIS는 Portable Operating System Interface 약자로 쉽게 설명을 드리면 다음과 같습니다.

   "유닉스 운영체제 계열의 표준을 맞춰보자."

POSIX(Portable Operating System Interface)란 응용 어플리케이션이 다양한 유닉스 계열 운영체제에서 호환성을 유지하면서 실행하도록 만든 표준 규약입니다. 대표적인 POSIX 규약은 다음과 같습니다. 
   - 리눅스 저수준 함수
   - 시스템 콜 테이블
   - 프로세스 통신용으로 쓰는 시그널 종류 

대부분 유닉스 계열 운영체제가 자신을 소개할 때 다음과 같은 문구를 볼 수 있습니다.

     "저희 운영체제는 POSIX 규약을 따릅니다."

이 문장을 달리 표현해볼까요?

   "다른 유닉스 계열 운영체제에서 실행하는 어플리케이션이 저희 운영체제에서도 잘 
       돌아갑니다.

운영체제의 핵심 가치는 호환성입니다. 그래서 POSIX 규약을 지키지 않는 유닉스 계열 운영체제는 살아남지 못합니다. 응용 어플리케이션은 각자 알고리즘과 구현 시나리오에 집중하고 리눅스 저수준 함수 세부 구현 내역과 리눅스 커널 동작에 신경을 쓸 필요가 없습니다.

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


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

"혹시 궁금한 점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답변 올려드리겠습니다!" 

Thanks,
Austin Kim(austindh.kim@gmail.com)


#Reference: 시스템 콜
시스템 콜 주요 개념 소개
유저 공간에서 시스템 콜은 어떻게 발생할까
시스템 콜 핸들러는 어떤 동작을 할까? 
시스템 콜 실행 완료 후 무슨 일을 할까?
시스템 콜 관련 함수  
시스템 콜 디버깅  

핑백

덧글

댓글 입력 영역