CentOS6.2 自定义系统调用
我使用的是CentOS6.2
1.下载内核
以linux-2.6.39.tar.bz2为例
2.解压缩
解压缩至/usr/src/kernels/linux-2.6.39
3.添加函数到内核映像中
系统调用必须编译到内核映像中去,此例放入linux-2.6.39/kernels/sys.c,也可以放入其他的.c文件,主要是功能联系相关
观察sys.c文件,找一个函数举例:
1 SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len) 2 { 3 int errno; 4 char tmp[__NEW_UTS_LEN]; 5 6 if (!capable(CAP_SYS_ADMIN)) 7 return -EPERM; 8 if (len < 0 || len > __NEW_UTS_LEN) 9 return -EINVAL; 10 11 down_write(&uts_sem); 12 errno = -EFAULT; 13 if (!copy_from_user(tmp, name, len)) { 14 struct new_utsname *u = utsname(); 15 16 memcpy(u->domainname, tmp, len); 17 memset(u->domainname + len, 0, sizeof(u->domainname) - len); 18 errno = 0; 19 } 20 up_write(&uts_sem); 21 return errno; 22 }
SYSCALL_DEFINE2只是一个宏,数字2表示该函数有2个参数,宏展开之后如下:
asmlinkage long sys_setdomainname(char __user* name, int len)
asmlinkage是限定词,这是一个编译指令,通知编译器通过栈传递函数参数,默认的是通过寄存器传参,所有的系统调用都需要这个限定词。
在sys.c文件中,加入自己写的系统调用:
1 asmlinkage int sys_sumtest(int number) 2 3 { 4 5 int i=0,sum=0; 6 7 printk("<0>""这是添加的系统调用\n"); 8 9 while(i<=number) 10 11 sum+=i++; 12 13 return sum; 14 15 }
4.注册系统调用号
在 linux-2.6.39/arch/x86/include/unistd_32.h 头文件中注册系统调用号
实例代码:
#define __NR_sumtest 333
5.填写系统调用表
linux-2.6.39/arch/x86/kernel/syscalls_table_32.S,在syscall_table(系统调用表)中对应于系统调用号的位置,填写系统调用函数。
实例代码:
ENTRY(sys_call_table)
.long sys_restart_syscall
.long sys_exit
.......
.......
.long sys_syncfs
.long sys_sumtest //333 本次添加的系统调用函数
6.编译、安装内核
另外一篇文章有详细过程
7.重启,使用新内核引导开机,测试系统调用
1 #include<stdio.h> 2 #include<string.h> 3 4 int main(int argc,char ** argv) 5 { 6 int temp; 7 int src=5; 8 if(argc>2) 9 printf("argument error!\n"); 10 else 11 { 12 if(argc==1) 13 temp=syscall(345,src); 14 else 15 { 16 src=atoi(argv[1]); 17 temp=syscall(345,src); 18 } 19 printf("sum of 1 to %d is tmp=%d\n",src,temp); 20 } 21 return 0; 22 }