例说linux内核与应用数据通信(一):添加一个系统调用
来源:互联网 发布:怎么做图书marc数据 编辑:程序博客网 时间:2024/05/01 14:45
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
应用不能访问内核的内存空间,为了应用和内核交互信息,内核提供一组接口,通过这组接口,应用可以发送请求,内核可以响应处理该请求,这组接口就是系统调用。
关于内核系统调用的实现查看本博客中这篇文章:应用不能访问内核的内存空间,为了应用和内核交互信息,内核提供一组接口,通过这组接口,应用可以发送请求,内核可以响应处理该请求,这组接口就是系统调用。
http://blog.csdn.net/shallnet/article/details/47113753
本文章以x86-32为例:
$ uname -aLinux localhost 2.6.32 #1 SMP Sat Jun 13 23:55:06 CST 2015 i686 i686 i386 GNU/Linux
第一步,在系统调用表中加入一个表项,表中为每一个有效的系统调用指定了惟一的系统调用号。系统调用表位于arch/x86/kernel/syscall_table_32.S文件中,在该文件中最后一行添加自己的系统调用表项,如下:
...... .long sys_preadv .long sys_pwritev .long sys_rt_tgsigqueueinfo /* 335 */ .long sys_perf_event_open .long sys_shallnet
虽然没有明确指定编号,但该系统调用已经按次序分配了337这个系统调用号,接下来就应该添加系统调用号。
第二步,添加系统调用号。在Linux中,每个系统调用被赋予一个系统调用号。这样,通过这个独一无二的号就可以关联系统调用。当用户空间的进程执行一个系统调用的时候,这个系统调用号就被用来指明到底是要执行哪个系统调用。在文件arch/sh/include/asm/unistd_32.h该列表中加入一行#define __NR_shallnet 337 :
......#define __NR_inotify_init1 332#define __NR_preadv 333#define __NR_pwritev 334#define __NR_rt_tgsigqueueinfo 335#define __NR_perf_event_open 336#define __NR_shallnet 337//#define NR_syscalls 337#define NR_syscalls 338......在内核源文件中该行为#define NR_syscalls 337,在系统调用执行的过程中,system_call()函数会根据该值来对用户态进程的有效性进行检查。如果这个号大于或等于NR_syscalls,系统调用处理程序终止。所以应该将原来的#define NR_syscalls 337修改为#define NR_syscalls 338。
第三步,实现shallnet系统调用。在文件kernel/sys.c最后添加如下函数:
SYSCALL_DEFINE0(shallnet)SYSCALL_DEFINE1(shallnet, int, arg){ printk(KERN_ALERT"My blog address: \"http://blog.csdn.net/shallnet\""); return arg + arg;}第四步,重新编译内核。依次执行:
make oldconfigmake bzImagemake modulesmake modules_installmake install第五步,重新启动系统然后进入刚新编译的系统,编写测试代码如下:
#include <stdio.h>#include <unistd.h>#include <sys/syscall.h>#define __NR_shallnet 337int main(int argc, const char *argv[]){ int ret; ret = syscall(337, 99); printf("shallnet() return: %d\n", ret); return 0;}编译执行该程序如下:
$ ./target_binshallnet() return: 198$ demsg......My blog address: "http://blog.csdn.net/shallnet"可以看到我们新加的系统调用执行成功了。
可见建立一个新的系统调用还是很容易的,但是不提倡这么做,系统调用需要一个系统调用号,需要修改内核代码,修改之后需要重新编译内核。linux系统应当尽量避免每出现一个新的抽象就加入一个新的系统调用,通常有其他的方法可以代替系统调用,比如说实现一个设备节点等。
本节源码下载:
http://download.csdn.net/detail/gentleliu/9035717
http://download.csdn.net/detail/gentleliu/9035717
1 0
- 例说linux内核与应用数据通信(一):添加一个系统调用
- 例说linux内核与应用数据通信系列
- 例说linux内核与应用数据通信(三):读写内核设备驱动文件
- 例说linux内核与应用数据通信(四):映射设备内核空间到用户态
- 例说linux内核与应用数据通信(二):proc虚拟文件系统
- 添加一个系统调用到Linux内核
- linux内核添加系统调用
- Linux内核添加系统调用
- linux内核添加系统调用
- linux内核--添加系统调用
- 【转】linux内核编译与系统调用的添加(适合3.0及以后版本内核)
- linux内核编译与系统调用的添加(适合3.0及以后版本内核)
- Linux操作系统-Lab3 更新内核与添加系统调用
- 添加一个系统调用,遍历内核进程
- linux 添加一个系统调用
- Linux操作系统分析(4)- 更新内核与添加系统调用
- Linux操作系统分析(4)- 更新内核与添加系统调用
- Qtopia应用程序与Linux内核数据通信介绍
- 站点访问量太对的解决办法(阿里2015)
- LeetCode2.1.17(Plus One)
- 学习
- GDI+ 使用指南(basic guiding of GDI plus )
- springmvc学习笔记(八)json传递数据
- 例说linux内核与应用数据通信(一):添加一个系统调用
- Android性能调优工具TraceView介绍
- 文章标题
- javascript-jquery插件--FlexGrid 用法参数
- QT跨线程的信号与槽[2]---后台SOCKET
- UVAoj 11178Morley's Theorem
- mysql 数据表的基本操作
- cdev_init和cdev_add之后在/dev目录下没有长出设备节点原因
- Android内存监测工具DDMS->Heap,内存分析工具->MAT