Art of Pr0gr4m

[Linux Kernel 5] system call 추가하기 본문

IT/Linux Kernel

[Linux Kernel 5] system call 추가하기

pr0gr4m 2020. 4. 24. 21:57

1. systemcall table에 시스템콜 추가하기

 

vi /arch/x86/entry/syscalls/syscall_64.tbl

 

arch/x86/entry/syscalls/syscall_64.tbl

 

 

마지막 라인에 새로운 시스템 콜 추가

 

<시스템콜번호> <ABI> <시스템콜이름> <엔트리포인트>

 

548 64 mycall __x64_sys_mycall

549 64 get_cpu_info  __x64_sys_get_cpu_info

 

 

2. 헤더 파일에 선언 추가하기

 

vi include/linux/syscalls.h

 

include/linux/syscalls.h

 

함수 선언 추가

(편의를 위해 예시에선 syscalls.h 파일 안에 구조체도 함께 정의)

 

struct cpu_info

{

    char vendor_id[16];

    char model_id[64];

    unsigned int cache_size;

};

 

asmlinkage long sys_mycall(void);

asmlinkage long sys_get_cpu_info(struct cpu_info *info);

 

 

3. 함수 정의하기

 

vi kernel/mycall.c

 

kernel/mycall.c

 

원하는 위치에 함수 정의

 

SYSCALL_DEFINEn 매크로 이용 (n은 인자 갯수)

 

SYSCALL_DEFINE2(함수 이름, 첫번째 자료형, 첫번째 자료이름, 두번째 자료형, 두번째 자료이름) 처럼 사용

 

boot_cpu_data는 arch/sh/include/asm/processor.h에 정의되어 있으며,

 

부팅 과정에서 프로세서 정보로 초기화됨

 

access_ok는 /arch/x86/include/asm/uaccess.h에 다음과 같이 정의되어 있다

 

#define access_ok(addr, size)

({

    WARN_ON_IN_IRQ();

    likely(!__range_not_ok(addr, size, user_addr_max()));

})

 

addr부터 size까지의 범위가 유효한 유저 프로세스 주소인지 확인하여 유효하지 않는 경우엔 0을 반환한다

 

put_user와 copy_to_user는 커널 영역의 데이터를 사용자 영역으로 복사한다

 

반대로 사용자 영역의 데이터를 커널 영역으로 복사하는 함수에는 get_user와 copy_from_user가 있다

 

그러나 사용자 영역의 데이터는 주로 인자로 넘기기 때문에 put_user와 copy_to_user가 주로 사용된다

 

copy_to_user는 복사할 길이를 직접 지정하지만 put_user는 1 | 2 | 4 바이트 값을 알아서 복사한다

 

 

4. 커널 빌드

 

Makefile

 

함수를 정의한 파일을 Makefile에 추가

 

이 후 make && sudo make install 로 빌드 및 설치

(처음 빌드라면 make menuconfig -> make -> sudo make install modules_install)

 

성공 하면 재부팅

 

 

5. 테스트

 

테스트용 코드 작성

 

test_syscall.c

 

실행 결과

 

./a.out 실행 결과

 

 

 

6. 커널 메시지 확인

 

dmesg로 메시지 확인

 

dmesg 결과

 

printk로 작성한 커널 메시지에서 a값과 b값 확인

 

 

 

이렇게 커널에 시스템콜을 등록하여 원하는 커널 서비스 루틴을 만들 수 있다