Chinaunix首页 | 论坛 | 博客
  • 博客访问: 17031
  • 博文数量: 7
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 114
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-06 21:17
文章分类
文章存档

2018年(1)

2014年(1)

2013年(5)

我的朋友

分类: LINUX

2013-09-28 11:01:26

简单练习了添加系统调用,算是内核学习的敲门砖。
内核版本更新太快,很多帖子提到的方式都过时了,甚至有些内核文件都已经不存在了。本次实验基于内核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



阅读(1448) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~