本文共 3553 字,大约阅读时间需要 11 分钟。
添加一个系统调用有以下几个步骤:
1. 在 kernel 的系统调用表 sys_call_table 中添加你的系统调用入口根据你用的内核位数(32/64bit) 选择需要修改的文件:arch/mips/kernel/scall32-o32.S ------> 32bit kernelarch/mips/kernel/scall64-64.S ------> 64bit kernel64bit内核,如果支持兼容32 bit ABI (o32, n32 ) 则还需修改 scall64-o32.S 或 scall64-n32.S以32bit 内核为例,在 arch/mips/kernel/scall32-o32.S 中找到宏定义 .macro syscalltable /* 系统调用号从 4000 开始 */ ...... ...... sys sys_faccessat 3 /* 4300 */ sys sys_pselect6 6 sys sys_ppoll 5 sys sys_unshare 1 sys sys_splice 4 sys sys_sync_file_range 7 /* 4305 */ sys sys_tee 4 sys sys_vmsplice 4 sys sys_move_pages 6 sys sys_set_robust_list 2 sys sys_get_robust_list 3 /* 4310 */ sys sys_ni_syscall 0 sys sys_ni_syscall 0 sys sys_ni_syscall 0 sys sys_ioprio_set 3 sys sys_ioprio_get 2 /* 4315 */ sys sys_wenxy_test 0 /* system call ID is 4316, wenxy add, 20091120 */ .endm...... 最后加入自定义的系统调用 sys_wenxy_test 于 sys_call_table 中, sys 为辅助宏,调用名后的数值 0 指示该系统调用所需的参数个数。只能加在 sys_call_table 的最后,否则会扰乱标准的系统调用。2. 实现系统调用可以在 arch/mips/kernel/syscall.c 中给出一个实现,如:....../* wenxy add begin, 20091119, a.m. */#include "/opt/bcm97405/kernel/stblinux-2.6.18/arch/mips/sibyte/cfe/cfe_api.h"asmlinkage int sys_wenxy_test(void){ uint64_t cfe_ept, cfe_handle; int n; //n = cfe_init(cfe_handle, cfe_ept); printk(KERN_EMERG "kernel, wenxy debug: into [%s], call [%s()]/n", __FILE__, __FUNCTION__); return 100;}/* wenxy add end */3. 修改 include/asm-mips/unistd.h根据你的内核位和支持的ABI版本修改相应的宏定义,32bit 内核需修改:#define __NR_Linux_syscalls 320 ---------> 321 (The number of linux syscalls)#define __NR_O32_Linux_syscalls 320 ---------> 321 (The number of linux O32 syscalls)相应的在其上的宏集的最后加入:.......#define __NR_ppoll (__NR_Linux + 302)#define __NR_unshare (__NR_Linux + 303)#define __NR_splice (__NR_Linux + 304)#define __NR_sync_file_range (__NR_Linux + 305)#define __NR_tee (__NR_Linux + 306)#define __NR_vmsplice (__NR_Linux + 307)#define __NR_move_pages (__NR_Linux + 308)#define __NR_set_robust_list (__NR_Linux + 309)#define __NR_get_robust_list (__NR_Linux + 310)#define __NR_ioprio_set (__NR_Linux + 314)#define __NR_ioprio_get (__NR_Linux + 315)/* wenxy add begin , 20091119, a.m. */#define __NR_wenxy_test (__NR_Linux + 316)/* wenxy add end */......4. 测试新的系统调用wenxy_testtest.c文件, C程序:#if 1#include <stdio.h>#include <linux/unistd.h>#include <sys/syscall.h>#include <errno.h>#else#include "/opt/bcm97405/kernel/stblinux-2.6.18/include/linux/unistd.h"#include "/opt/bcm97405/kernel/stblinux-2.6.18/include/sys/syscall.h"#endif//#define __NR_getjiffies 320//#define __NR_wenxy_test 319#define __NR_wenxy_test (__NR_Linux + 316)_syscall0(int, wenxy_test);int main(){ long jiffies; int n;// jiffies = syscall( __NR_getjiffies );// printf( "Current jiffies is %lx/n", jiffies ); n = 0; //n = syscall(__NR_wenxy_test); n = wenxy_test(); printf("Wenxy: syscall return value is [%d], system call ID=[%d]/n", n, __NR_wenxy_test); return 0;}编译test.c的命令:mipsel-linux-gcc -I/opt/bcm97405/kernel/stblinux-2.6.18 test.c或者自己写汇编程序:用重新编译后的内核启动,如下程序测试之:.text.globl main.ent mainmain: li $2, 4316 /* wenxy_test 的系统的调用号 */ syscall.end main其中 MIPS 下系统调用的约定为:v0: 用于置系统调用号a0~a3: 置前四个参数,后面的参数用栈传syscall 系统调用触发指令编译 gcc cat.S -o a.out执行 ./a.out正确的话应有如下输出:# a.outkernel, wenxy debug: into [arch/mips/kernel/syscall.c], call [sys_wenxy_test()]Wenxy: syscall return value is [100], system call ID=[4316]PS. a. 可以用dmesg查看内核日志,或者用strace a.out来跟踪系统调用信息。b. 参考资料: http://www.ibm.com/developerworks/cn/linux/l-system-calls/index.htmlhttp://www.diybl.com/course/3_program/hb/hbjs/200798/70400.html#转载地址:http://hisqi.baihongyu.com/