简单练习了添加系统调用,算是内核学习的敲门砖。
内核版本更新太快,很多帖子提到的方式都过时了,甚至有些内核文件都已经不存在了。本次实验基于内核3.10.12,验证ok。
尝试了3种方式,添加了3个函数:
【1】直接在sys.c中添加函数实现
1)在kernel/sys.c最后添加:
SYSCALL_DEFINE0(getownerage)
{
return 100;
}
2)在include/linux/syscalls.h中添加函数声明:
asmlinkage long sys_getownerage(void);
3)在arch/x86/syscalls/syscall_32.tbl最后添加异常处理表项
351 i386 getownerage sys_getownerage
【2】新增加内核文件
1)在kernel下增加name.c,实现代码:
#include
#include
#include
SYSCALL_DEFINE2(getownername, char __user *, name, int __user *,len)
{
char buf[]="kevin";
int sz = sizeof(buf);
if(NULL == name)
return -1;
memcpy(name, buf, sz);
*(name + sz) = '\0';
*len = sz;
return 0;
}
2)在include/linux/syscalls.h中添加函数声明:
asmlinkage long sys_getownername(char __user *name, int __user* len);
3)在arch/x86/syscalls/syscall_32.tbl最后添加异常处理表项
352 i386 getownername sys_getownername
4)修改kernel/Makefile, 在obj-y定义的末尾加上name.o
【3】增加一个文件夹info
1)在info中添加info.c和Makefile
2)info.c内容:
#include
#include
#include
SYSCALL_DEFINE5(getownerinfo, char __user *, name, int, namelen, int, age, char __user *, info, int __user*, infolen)
{
char buf[100];
char sz = 0;
if(NULL == name || NULL == info)
{
return -1;
}
if(namelen > infolen)
{
return -1;
}
memset(info,'\0',infolen);
sprintf(buf, "owner name is :%s, age is:%d",name,age);
sz = strlen(buf);
memcpy(info, buf, sz + 1);
return 0;
}
3)在include/linux/syscalls.h中添加函数声明:
asmlinkage long sys_getownerinfo(char __user* name, int namelen, int age, char __user * info, int __user * infolen);
4)在arch/x86/syscalls/syscall_32.tbl最后添加异常处理表项
353 i386 getownerinfo sys_getownerinfo
5)修改kernerl/Makefile,添加:
obj-y += info/
6)编辑kernel/info/Makefile,添加内容:
obj-y = info.o
重新编译内核,随便写点测试代码,基本ok!
比如:
#define __GET_AGE__ 351/*定义系统调用号*/
int main()
{
int age = syscall(__GET_AGE__);
printf("age is:%d\n",age);
return 0
}
【补充说明】
1.系统调用是通过int 0x80的软中断实现的,当应用程序传递系统调用号给内核,内核首先触发这个软中断,转到对应的异常处理程序处执行。系统调用很多种,异常处理程序根据系统调用号转到真正的系统调用函数执行。arch/x86/syscalls/syscall_32.tbl维护了一个系统调用表,用于查找对应的系统调用函数
2.宏SYSCALL_DEFINEx(name,...)展开就是asmlinkage long sys_name(...)的形式,这就和函数声明一致了。x代表参数个数。 指针修饰一般加个__user。
3.新增文件name.c所以也许要新增编译选项,一个文件夹下一个Makefile,所以直接修改kernel/Makefile。添加一个name.0
4.对于info.c需要在kernerl/info文件夹下增加一个Makefile;另外还需要修改kernel/Makefile,增加
obj-y += info/
是为了告诉编译器需要到info路径下编译。
5.关于Makefile规则,详细参考:
http://blog.csdn.net/danforn/article/details/1424619
阅读(1491) | 评论(0) | 转发(0) |