커널 Makefile 구조
- obj-y
- obj-y에 들어간 파일만 커널에 컴파일되어 포함됨(바이너리)
- obj-y += foo.o
- obj-$ (CONFIG_*)
- 조건부로 파일 포함할 때
- CONFIG_*이 .config파일에 정의된 대로 결정됨
- obj-$(CONFIG_MYDRIVER) += bar.o
printk
커널내에서 로그 출력
로그 레벨
| level0 | KERN_EMERGE | 시스템 불안정 |
|---|---|---|
| level1 | KERN_ALERT | 당장 조치 요구 |
| level2 | KERN_CRIT | 심각한 상황 |
| level3 | KERN_ERR | 오류 발생 |
| level4 | KERN_WARNING | 경고 |
| level5 | KERN_NOTICE | 일반적인 상황 |
| level6 | KERN_INFO | 참고할만한 상황 |
| level7 | KERN_DEBUG | 디버깅 |
SYSTEMCALL_DEFINE 매크로
시스템콜 정의하기 위한 매크로
- 형식: SYSCALL_DEFINE(name, type1, arg1, type2, arg2, ...)
- <n>: 인자 수
- name: 시스템 콜 이름
- 뒤에: 인자들의 타입과 이름 쌍
커널에 새로운 코드 추가
<kernel/new_syscall.c>
#include <linux/kernel.h>
#include <linux/syscalls.h>
SYSCALL_DEFINE1(new_syscall, int, code)
{
printk(KERN_INFO "hello world!! %d \n", code);
return code + 1;
}
를 커널에 추가해 보자.
Makefile 수정
new_syscall.o를 커널에 포함시키기 위해 다음과 같이 추가.
obj-y += new_syscall.o
다음과 같이 추가.
시스템 콜 번호 추가
- 시스템 콜은 고유 번호를 갖고 호출
- 시스템콜 호출되면 고유의 번호를 통해 함수를 찾음
_SYSCALL매크로 사용하여 정의__NR_syscalls는 시스템콜의 갯수__NR_syscalls정의 앞에다 하는 것이 일반적- 시스템 콜 갯수(_NR_syscalls) 1 증가시켜야함
__NR_syscalls 는 <include/uapi/asm-generic/unistd.h>에 있음
커널 재빌드
syscall함수이용해서 시스템콜 호출
syscall함수는 <unistd.h>헤더파일 include해야함
이제 사용자 영역에서 제작한 시스템콜을 호출해보자
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#define __NR_new_syscall 451
int main()
{
int result = syscall(__NR_new_syscall, 10);
printf("result: %d\n", result);
return 0;
}
순서
1. 커널 코드</kernel/에 SYSCALL_DEFINE 로 새 시스템 콜 정의
/kernel/new_syscall.c 작성
#include <linux/kernel.h>
#include <linux/syscalls.h>
SYSCALL_DEFINE1(new_syscall, int, code)
{
printk(KERN_INFO "Hello world~!! %d \n", code);
return code + 1;
}
2. /kernel/Makefile 수정
obj-y += new_syscall.o
빌드가 되는 목적파일에, new_syscall.o도 추가해주는 작업인듯
3. 커널에 새로운 시스템콜 추가
/include/uapi/asm-generic/unistd.h 에 시스템콜 추가
#define __NR_new_syscall 451 // 새로운 시스템콜 정의
__SYSCALL(__NR_new_syscall, sys_new_syscall) // 시스템콜 번호와 실제 커널 함수 매핑
//시스템콜 테이블에 쓰이는 매크로
...
...
#define __NR_syscalls 452 // 시스템콜 수 1증가시켜서 452개
4. 커널 재빌드
진행
5. 새로운 시스템콜 사용 예제 프로그램
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#define __NR_new_syscall 451
int main()
{
int result = syscall(__NR_new_syscall, 10);
printf("result: %d\n", result);
return 0;
}
툴체인을 사용하여 aarch64를 타겟으로 크로스 컴파일 진행 (로컬내의 그냥 gcc로 하면 안됨..)
빌드 완료 후
- rootfs의 ext4파일을 mount
- 실행파일을 rootfs의 /usr/bin 에 복사
- mount 해제
6. 빌드한 프로그램, QEMU에서 실행
완료
'Linux' 카테고리의 다른 글
| ls 명령어 분석 with strace (1) | 2025.07.29 |
|---|---|
| Kernel 및 System call 디버그 with GDB (0) | 2025.07.28 |
| Makefile (2) | 2025.07.24 |
| OS 기초 이론 (0) | 2025.07.23 |
| Rootfs와 Kernel 빌드 (feat Makefile) (0) | 2025.07.21 |