2024. 11. 28. 15:26ㆍ디바이스 드라이버
아래와 같이 간단한 문구를 출력하는 시스템 콜을 추가해본다.
먼저 linux/kernel 부분에 들어가서 위와 같은 vim 파일을 만든다.
여기서 linux/kernel.h는 커널 소스 코드에서 사용되는 헤더 파일로, 다양한 유틸리티 함수와 매크로, 커널 코드에서 자주 쓰이는 정의들을 포함하고 있다. 지금 우리가 linux/kernel.h 헤더 파일을 사용한 이유는 printk함수를 사용하기 위해서이다.
printk함수는 커널 로그를 출력하기 위한 함수로 stdio.h의 printf함수와 사용법이 동일하다. 다만 printk함수에서는 맨 앞에 로그레벨을 추가할 수 있는데 종류는 아래와 같다.
KERN_EMERG , 0 , 시스템 불안정
KERN_ALERT , 1 , 당장 조치 요구됨
KERN_CRIT , 2 , 심각한 상황
KERN_ERR , 3 , 오류 발생
KERN_WARNING , 4 , 경고
KERN_NOTICE , 5 , 일반적인 상황
KERN_INFO , 6 , 참고할만한 상황
KERN_DEBUG , 7 , 디버깅
위의 예제에서 KERN_INFO로 로그 레벨을 설정했기 때문에 5,6,7 로그는 무시하게 된다. ( 코드가 경고 이상의 상황이 됐을 때 로그 출력)
linux/syscalls.h 헤더파일은 커널에서 시스템 호출과 관련된 함수 및 매크로를 정의한 헤더 파일이다.
시스템 콜 함수를 정의하기 위해서는 SYSCALL_DEFINE함수를 사용한다. 위에서 DEFINE 옆에 숫자는 인자 수를 나타낸다.
위와 같이 코드를 입력한 후 저장했다면, linux/kernel의 Makefile을 수정해줘야한다.
kernel의 Makefile을 열면 맨 위에 위와 같은 문구가 있다. obj-y부분은 kernel이 실행될 때 필요한 목적파일들이다.
밑에 있는 obj-$는 커널의 Makefile에서 조건부로 특정 목적 파일을 빌드할 때 사용된다. 이는 Kconfig 파일에서 설정된 CONFIG_ 옵션에 따라 obj-y 또는 obj-m으로 동작을 한다.
이 명령어를 사용하면 CONFIG_ 옵션이 무엇인지 확인할 수 있다.
다음과 같이 groups.o 목적파일은 obj-y에 들어가는 사실을 알 수 있다.
이러한 CONFIG_ 옵션은 menuconfig에서 설정할 수 있다.
linux로 돌아가서 ARCH=arm64 make menuconfig를 실행한 후 /키로 검색창에 들어가서 MODULES를 검색해보면
위와 같이 y로 설정된 점을 확인할 수 있다.
USERMODE_DRIVER는 n이라고 설정되어있는데 이는 아무것도 설정되지 않았음을 의미한다.
우리가 작성한 코드도 obj-y에 등록을 해야 커널이 실행될 때 코드가 작동하므로
Makefile에 아래와 같이 넣어준다.
커널의 Makefile에 코드를 넣어줬으면 이제 DEFINE매크로에 번호를 매겨줘야한다.
unistd.h는 Linux 커널 소스 코드에서 시스템 호출 번호와 관련된 정의를 제공하는 헤더 파일이다. 이 곳에서 시스템 콜 번호를 정의할 수 있다.
위와 같이 매크로와 함께 번호를 매겨준다.
여기서 NR_new_syscall은 시스템 호출 번호를 정의하고, sys_new_syscall은 해당 번호와 매핑된 커널 함수로, 시스템 호출이 실행될 때 실제로 수행되는 작업을 정의한다.
그 다음 매크로를 추가해서 변경사항이 생겼으니 linux를 다시 make해줘야한다.
매크로를 사용하는 간단한 c프로그램을 작성한 후
툴 체인을 사용해 목적파일로 만들어 준다.
그 다음 타겟의 rootfs(루트 파일 시스템)에 빌드한 프로그램을 복사해줘야한다. 그러기 위해선 /mnt 디렉토리에 mount(연결)를 해야한다.
hello 파일을 복사해서 넣으려고 하지만 권한이 없기 때문에 실패하는 모습을 볼 수 있다.
그럴 땐 sudo 명령어를 사용해야한다.
그 다음 sync 후 umount(연결해제)를 해준다.
qemu에 들어가서
hello 파일을 실행시키면 hello 파일 안에 있는 new_syscall이 QEMU 내부에서 실행중인 Linux 커널로 요청되고, 커널은 요청된 함수를 실행시켜서 결과값을 hello에 반환한다.
'디바이스 드라이버' 카테고리의 다른 글
시스템 콜 추가하기 (실습) (0) | 2024.12.10 |
---|---|
GDB를 통한 디버깅 (0) | 2024.12.02 |
새로운 시스템 콜 추가하기 (1) (0) | 2024.11.27 |
Makefile 실습 (1) | 2024.11.26 |
QEMU에서 리눅스 실행하기 (1) | 2024.11.23 |