(1) 操作系统的主要功能是为管理硬件资源和为应用程序开发人员提供良好的环境来使应用程序具有更好的兼容性, 为了达到这个目的, 内核提供一系列具备预定功能的多内核函数, 通过一组称为系统调用 (system call) 的接口呈现给用户. 系统调用把应用程序的请求传给内核, 调用相应的的内核函数完成所需的处理, 将处理结果返回给应用程序.
1. 通过中断使进程切换到内核模式[i386 为 int 80h 指令完成]
系统调用中断的入口为 syscall(调用号),
2. 查找系统调用跳转表, 并调用相应函数:
3.Linux-2.6.32.60/arch/x86/include/asm/unistd_32.h 中定义了所有系统调用的编号
4. 跳转表以系统调用编号为下标, 总个数由 NR_syscalls 确定
5. 每个系统调用都有自己的编号, 而且是固定的, 如果想修改编号, 则要改变跳转表的顺序.
6. 没有定义的跳转表项, 一律指向函数
- sys_ni_syscall()/*kernel/sys.c*/
- {
- return -ENOSYS;
- }
第一步:
解压缩内核源码包 Linux-2.6.32.60.tar.bz2 到目录 / usr/src 下
解压缩命令 tar xvf Linux-2.6.32.60.tar.bz2 /usr/src
解压缩后在 / usr/src 中多了一个 Linux-2.6.32.60 的文件夹, 之后的修改源码的工作都是在这个文件夹中进行.
第二步:
修改系统调用表文件
Linux-2.6.32.60/arch/x86/kernel/syscall_table_32.S
在文件中最后一组. long 代码后添加一行
.long sys_mycall
第三步:
修改系统调用号文件, 增加函数的系统调用号, 并将系统总调用号增加到相应文件中.
Linux-2.6.32.60/arch/x86/include/asm/unistd_32.h
在文件最后增加系统调用
#define __NR_mycall 337 // 自己函数的调用号
同时修改系统调用函数总数, 这是可以调用的编号上限
#define NR_syscalls 338
第四步:
增加系统调用声明, 修改文件
Linux-2.6.32.60/include/Linux/syscalls.h
在文件后添加代码
asmlinkage long sys_mycall(int num);
第五步:
添加系统调用函数的实现, 修改文件
Linux-2.6.32.60/kernel/sys.c
在文件后添加代码, 必须和第四步的声明完全对应
printk()的输出可以在终端中用 dmesg 命令查看
1 asmlinkage long sys_mycall(int num){ 2 // 在此处加入自己的代码 3 printk("This is my syscall from kernel.\n"); 4 printk("current pid is:%d.\n",current->pid); 5 return num; 6 }
第六步: 内核编译
重新编译内核, 用新编译的内核作为启动项.
第七步: 打开终端编写测试代码, 代码中调用你自己写的系统函数, 编译运行查看运行结果是否调用成功.
也可以用 dmesg 命令查看进程的 printk()函数的输出.
调用方式: syscall(系统调用号, 参数列表);
创建一个. c 的源文件, 写入测试代码.
- #include <stdio.h>
- int main()
- {
- printf("The return value is: %d.\n", syscall(337, 5));
- return 0;
- }
- (2)
来源: http://www.bubuko.com/infodetail-3108783.html