前面我们学习了在内核中添加自己的代码,这次我们在内核中添加一个自己的系统调用,就像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! "); 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 "); 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 ",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#
以上就完成了一个系统调用的全过程,相信同学们即学会了如何在内核中添加一个系统调用,也学会了应用程序调用系统调用的全过程了,是不是觉得很赞?!!!!!!!!!!哈哈哈哈反正我觉得是有收获的!