Application 과 커널 간의 인자를 어떻게 전달하는지를 살펴보기 위한 간단한 시스템 콜을 작성하고 있다.

시스템 콜 작성

먼저 unistd.h 파일에 다음을 추가한다.

#define __NR_show_mult          261

entry.S 파일에 다음을 추가한다.

        .long SYMBOL_NAME(sys_ni_syscall)       /* sys_set_tid_address */
        .long SYMBOL_NAME(sys_newsyscall)       /* sys_set_tid_address */
        .long SYMBOL_NAME(sys_gettaskinfo)      /* sys_set_tid_address */
        .long SYMBOL_NAME(sys_show_mult)        /* sys_set_tid_address */   // 추가
 
        .rept NR_syscalls-(.-sys_call_table)/4
                .long SYMBOL_NAME(sys_ni_syscall)
        .endr

이제 시스템 콜 함수를 작성한다. 파일이름은 newfile2.c 이고, kernel 디렉토리 아래에 둔다.

#include <linux/unistd.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm-i386/uaccess.h>
 
asmlinkage int sys_show_mult(int x, int y, int *res)
{
        int error, compute;
 
        error = verify_area(VERIFY_WRITE, res, sizeof(int));
        if(error)
                return error;
 
        compute = x*y;
        put_user(compute, res);
        return(0);
}

Makefile 에 newfile2.o 를 추가한 후, 커널 컴파일을 해서 새로운 커널 이미지로 부팅한다.

Application 작성

파일 이름은 test2.c 이고 /root 아래에 둔다.

#include <linux/unistd.h>
#include <errno.h>
 
_syscall3(int, show_mult, int, x, int, y, int *, result);
 
main()
{
        int mult_ret = 0;
        int x=2;
        int y=5;
 
        printf("%d * %d = %d\n", x,y,mult_ret);
        show_mult(x,y,&mult_ret);
        printf("%d * %d = %d\n", x,y,mult_ret);
}

/usr/include/asm/unistd.h 파일에 다음을 추가한다.

#define __NR_show_mult          261

마지막으로 컴파일을 한다. 그리고 나서 a.out 을 실행한다.

2 * 5 = 0
2 * 5 = 10

위와 같은 결과가 나온다면 성공이다.

동작 설명

unistd.h 파일을 보면, _syscall 에 대한 여러가지 함수들이 선언되어 있다. 앞에서는 거의 _syscall0 를 사용했었다. 이 함수는 인자가 없는 시스템 콜에 사용되었다. 여기서 사용된 _syscall3 의 경우, 총 8개의 인자를 받는다. 사용자 영역에서 x,y, &mult_ret 인자를 커널로 넘겼다.
put_user() 를 사용하기 전에 res 라는 사용자 공간에 쓰기가 가능한지 확인하기 위해 verify_area() 라는 커널 내부 함수를 사용하였다.

  • computer/embedded/시스템_콜_이해하기_-_3.인자_전달하기.txt
  • Last modified: 4 years ago
  • by likewind