在内核中添加系统调用

前面我们学习了在内核中添加自己的代码,这次我们在内核中添加一个自己的系统调用,就像open/close一样的函数!

当我们应用程序调用open close函数时: open close函数是经过libc.so 库调用syscall函数,然后syscall函数再经过SWI调用内核的系统调用的;

所有我们写了一个系统调用之后,也要实现这样一个过程,才能让应用层正常调用系统调用.

  vim  calls.S  为自己的函数注册系统调用号378

385                 CALL(sys_syncfs)
386                 CALL(sys_sendmmsg)
387 /* 375 */       CALL(sys_setns)
388                 CALL(sys_process_vm_readv)
389                 CALL(sys_process_vm_writev)
390 /* 378 */       CALL(sys_my_add)
391 #ifndef syscalls_counted
392 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
393 #define syscalls_counted
394 #endif
395 .rept syscalls_padding
396                 CALL(sys_ni_syscall)
397 .endr

   vim arch/arm/include/asm/unistd.h 声明自己的系统调用函数 407行

403 #define __NR_sendmmsg                   (__NR_SYSCALL_BASE+374)
404 #define __NR_setns                      (__NR_SYSCALL_BASE+375)
405 #define __NR_process_vm_readv           (__NR_SYSCALL_BASE+376)
406 #define __NR_process_vm_writev          (__NR_SYSCALL_BASE+377)
407 #define __NR_my_add                     (__NR_SYSCALL_BASE+378)
408 
409 /*
410  * The following SWIs are ARM private.
411  */
412 #define __ARM_NR_BASE                   (__NR_SYSCALL_BASE+0x0f0000)
413 #define __ARM_NR_breakpoint             (__ARM_NR_BASE+1)
414 #define __ARM_NR_cacheflush             (__ARM_NR_BASE+2)
415 #define __ARM_NR_usr26                  (__ARM_NR_BASE+3)

  在 arch/arm/kernel目录下创建一个mysyscall文件夹: 并在文件夹内:touch mysyscall.c mysyscall.h Makefile三个文件,写入如下代码,然后编译内核,并刷机,这样就把自己的syscall编译到内核了.

  mysyscall.c

  

  1 #include <linux/init.h>
  2 #include <linux/sched.h>
  3 #include <linux/module.h>
  4 #include "mysyscall.h"
  5 /* asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
  6                                       loff_t offset, loff_t len)
  7  {
  8          return sys_fadvise64_64(fd, offset, len, advice);
  9  }                                                          */
 10 //asmlinkage:表示将来这段代码是要由汇编来调用的。
 11  asmlinkage long sys_my_add(int a,int b)
 12  {
 13         printk("this is liuye's syscall!\n");
 14          return a+b;
 15  }
 16 
 17 //module_init(sys_my_add);
 18 MODULE_LICENSE("GPL");

  mysyscall.h

  1 #ifndef __MYSYSCALL_H_
  2 #define __MYSYSCALL_H_
  3 
  4  asmlinkage long sys_my_add(int a,int b);
  5 
  6 
  7 #endif

  makefile

  1 obj-y += mysyscall.o

  vim ../Makefile

 74 AFLAGS_iwmmxt.o                 := -Wa,-mcpu=iwmmxt
 75 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 76 # 在这层malefile中添加下一曾Makefile路径
 77 obj-y  += mysyscall/
 78 

  之后 make -j4 利用SD卡刷机 系统调用添加到内核中了;

  然后我们要制作一个包含mysyscall的库:在PC机上随便找一个文件夹:touch my_add.c my_add.h 写入如下代码.并编译成动态库:

  vim my_add.c

  1 //这三行是为了调用syscall而包含的头文件和宏定义:可以man syscall查看
  2 #define _GNU_SOURCE         /* See feature_test_macros(7) */
  3 #include <unistd.h>
  4 #include <sys/syscall.h>   /* For SYS_xxx definitions */
  5 #include <stdio.h>
  6 int my_add(int a ,int b)
  7 {
  8         printf("this is liuye's app\n");
  9         return  syscall(378,a,b);
 10 
 11 }

  vim my_add.h

  1 #ifndef __MY_ADD_H_
  2 #define __MY_ADD_H_
  3 
  4 extern int my_add(int a, int b);
  5 
  6 #endif

  把上面的my_add.c my_add.h制作成动态库:生成libadd.so

[liuye@LiuYe 01syscall]$>arm-linux-gcc -fPIC -c -o my_add.o my_add.c
[liuye@LiuYe 01syscall]$>arm-linux-gcc my_add.o -shared -o libadd.so

  然后写一个应用程序来调用下我们系统调用:touch test.c

  vim test.c

  1 #include <stdio.h>
  2 #include "my_add.h"
  3 //#include <my_add.h>
  4 int main(void)
  5 {
  6         int sum;
  7         sum = my_add(1,2);
  8         printf("sum = %d\n",sum);
  9         return 0;
 10 }
77     使用arm-linux-gcc编译test.c代码,需要链接动态库 -L指定路径  -l指定库名
78     生成可执行文件:arm-linux-gcc test.c -o test -L./ -ladd
79     复制库文件和可执行文件到共享文件夹:cp libadd.so test /myroot
81     把新编译的内核copy到SD卡,刷机;
82     PC端:1 开启共享服务
83           2 minicom链接开发板
84             mount -t nfs -o nolock,rw 192.168.1.10:/myroot /mnt
85             cd /mnt
86             cp libadd.so /lib/ 放到根下lib下,在运行的时候不用指定路径
87             ./test  运行即
root@board liuye_dir#./test 
this is liuye's app
[ 1817.020000] this is liuye's syscall!
sum = 3
root@board liuye_dir#

  以上就完成了一个系统调用的全过程,相信同学们即学会了如何在内核中添加一个系统调用,也学会了应用程序调用系统调用的全过程了,是不是觉得很赞?!!!!!!!!!!哈哈哈哈反正我觉得是有收获的!

猜你喜欢

转载自www.cnblogs.com/axjlxy/p/8964389.html