Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

848
469
422438


[라즈베리파이] 시스템 콜 - 유저 공간에서 시스템 콜 발생 11. 시스템 콜

유저 공간에서 커널 공간까지 어떤 코드로 시스템 콜을 구현했는지 분석을 시작합니다. 유저 모드에서 시스템 콜을 발생하면 커널 모드로 어떻게 스위칭하고 이후 시스템 콜 핸들러가 실행하는지 파악하는 것입니다.

가장 먼저 이런 의문이 생깁니다. 시스템 콜은 실행 시작점은 어디일까요? 
유저 공간에서 리눅스 저수준 함수를 호출했을 때가 시스템 콜 실행의 출발점입니다. 다음 전체 시스템 콜 흐름도에서 검은색으로 된 부분입니다.
 
리눅스 저수준 함수를 호출하면 실행하는 GNU C 라이브러리(glibc)가 어떤 흐름올 시스템 콜을 호출하는지 알아봅시다.

GNU C 라이브러리 실행 흐름
유저 공간에서 시스템 콜을 실행하기 위해서는 저수준 표준 함수를 호출해야 합니다.
저수준 표준 함수는 glibc 라이브러리에 구현돼 있어 실제 시스템 콜을 발생하는 코드를 확인하기 어렵습니다. 

glibc란 라이브러리 파일의 정체는 무엇일까요? glibc는 라즈베리파이에서 다음 경로에 있는 libc.a란 파일입니다.
root@raspberrypi:/home/pi# ls /usr/lib/arm-linux-gnueabihf/libc.a
/usr/lib/arm-linux-gnueabihf/libc.a

libc.a 를 리눅스에서 제공하는 라이브러리라고 하며 표준 입출력 함수과 프로세스 생성 요청과 같은 핵심 동작을 수행합니다.

이번 시간에는 libc.a 파일에 있는 어셈블리 코드를 열어서 시스템 콜 호출을 어떻게 실행하는지 점검합시다. liba.c에 있는 파일을 어셈블리 코드로 변환하려면 라즈베리파이에서 기본으로 제공하는 objdump라는 바이너리 유틸리티를 실행하면 됩니다.

다음과 같은 명령어를 입력하면 libc.a에 구현된 어셈블리 코드를 glibc_code.txt 파일로 저장할 수 있습니다.
root@raspberrypi:/home/pi# objdump –d > glibc_code.txt

이번에는 GNU C 라이브러리가 어떤 계층으로 구성됐는지 알아봅시다.

저수준 표준 함수인 fork(), exit() open(), write(), exit() 함수를 호출하면 GNU C 라이브러리 함수를 통해 시스템 콜을 실행합니다. 리눅스 저수준 함수를 호출하면 GNU C 라이브러리에서 시스템 콜을 발생한다는 것입니다.

이런 의문이 생깁니다. 이전 절에서 시스템 콜은 ARM 프로세서 “svc” 어셈블리 명령어인 Supervisor Call로 소프트웨어 인터럽트 방식으로 동작한다고 설명했습니다. GNU C 라이브러리 어딘가에 이 명령어를 실행하는 코드가 있다는 것입니다.
GNU C 라이브러리는 크게 3개 계층으로 분류할 수 있습니다.

리눅스 저수준 함수 인터페이스
유저 어플리케이션에서 직접 호출하는 표준 함수 인터페이스입니다. 이를 래퍼(Wrapper) 함수라고도 합니다. 위 그림에서 화살표로 표시된 부분입니다. 
리눅스 저수준 프로그램에서 fork() 이란 함수를 호출했다고 가정합시다. fork() 함수는 공용 인터페이스입니다. 어떤 아키텍처(x86, ARM, ARM64, PowerPC)에서도 fork() 함수를 호출하는 진입 경로는 같다는 것입니다.

표준 함수 계층
CPU 아키텍처에 무관한 표준 인터페이스 계층입니다. ARM32, ARM64, x86, x86_64 아키텍처에서 공용으로 처리하는 루틴입니다. 리눅스 저수준 프로그램은 실행하는 CPU에 무관하게 작성되어 있습니다. 리눅스 시스템이 구동하는 아키텍처에 독립적인 코드입니다.
리눅스 시스템 프로그램은 어떤 CPU 아키텍처에서도 구동할 수 있게 인터페이스를 구성해야 합니다.

아키텍처 의존적 코드
마지막 계층은 GNU C 라이브러리 가장 하단에 있는 아키텍처에 의존적인 코드입니다. 리눅스 저수준 프로그램을 실행하는 환경에 따라 아키텍처에 의존적인 코드는 바뀝니다. 라즈베리파이는 ARM32(Aarch32) 아키텍처이니 이 ARM32에 맞는 어셈블리 코드로 구성되어 있습니다. 만약 최신 안드로이드 디바이스의 경우 ARM64(Aarch64) 어셈블리 코드로 아키텍처 의존적인 코드는 구성되어 있습니다.

이 계층에서 Supervisor 명령어를 실행해서 소프트웨어 인터럽트를 발생하는 코드를 분석하겠습니다.


#Reference 시스템 콜


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

.


핑백

덧글

댓글 입력 영역