原文:https://blog.csdn.net/sdulibh/article/details/51889279

向linux内核添加系统调用,一是通过编译内核添加,二是通过内核模块的方式添加:

一:编译内核

第一步,下载内核版本。(我用的是2.6.39.2)
               然后在指定的目录下解压。
-------------------------------------------------------------------------------------
第二步,在arch/x86/include/asm/unistd_32.h
文件中添加系统调用号。
-------------------------------------------------------------------------------------
第三步,在arch/x86/kernel/syscall_table.s
文件中添加相应的表项。
-------------------------------------------------------------------------------------
第四步:实现系统调用的服务历程。
 理论上,这个函数的位置没有固定,最好加在arch/x86/kernel/目录
下的文件里面。我这次是加在arch/x86/kernel/sys_i386_32.c文件中
-------------------------------------------------------------------------------------
第五步:重新编译内核。
5.1,内核使用默认的配置,make menuconfig直接选择exit退出
5.2,使用如下命令编译内核
-------------------------------------------------------------------------------------
第六步:用户态测试系统调用。(注意内核安装好后,重启后选择新的内核)
运行结果:
-------------------------------------------------------------------------------------

二: 使用内核模块方式添加简单系统调用

1,为什么要使用内核模块的方式添加系统调用?

    1.1,编译内核的方式费时间,一般的PC机都要两三个小时。
    1.2,不方便调试,一旦出现问题前面的工作都前功尽弃。
-------------------------------------------------------
2,首先要获取系统调用表sys_call_table的地址(虚拟地址)
   因为sys_call_table在内核中没有导出,可以使用如下命令查看。
 
  1. cat /proc/kallsyms | grep sys_call_tables
注意点:当我把模块在一个机子上运行成功后,如果移植到另外一个机子上马上就会出现
        错误,为什么呢?因为每个机子上sys_call_table的地址可能不一样。
-------------------------------------------------------
3,需要查看预留的系统调用号。
  可以到arch/x86/include/asm/unistd.h文件中查看预留的系统调用号。
可以看出223就是一个预留的系统调用号。
-------------------------------------------------------
4,实例:

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/unistd.h>
  5. #include <asm/uaccess.h>
  6. #include <linux/sched.h>
  7. #define my_syscall_num 223
  8. //如下的这个值要到你机子上查。cat /proc/kallsyms | grep sys_call_table
  9. #define sys_call_table_adress 0xc1511160
  10. unsigned int clear_and_return_cr0(void);
  11. void setback_cr0(unsigned int val);
  12. asmlinkage long sys_mycall(void);
  13. int orig_cr0;
  14. unsigned long *sys_call_table = 0;
  15. static int (*anything_saved)(void);
  16. unsigned int clear_and_return_cr0(void)
  17. {
  18. unsigned int cr0 = 0;
  19. unsigned int ret;
  20. asm("movl %%cr0, %%eax":"=a"(cr0));
  21. ret = cr0;
  22. cr0 &= 0xfffeffff;
  23. asm("movl %%eax, %%cr0"::"a"(cr0));
  24. return ret;
  25. }
  26. void setback_cr0(unsigned int val) //读取val的值到eax寄存器,再将eax寄存器的值放入cr0中
  27. {
  28. asm volatile("movl %%eax, %%cr0"::"a"(val));
  29. }
  30. static int __init init_addsyscall(void)
  31. {
  32. printk("hello, kernel\n");
  33. sys_call_table = (unsigned long *)sys_call_table_adress;//获取系统调用服务首地址
  34. anything_saved = (int(*)(void)) (sys_call_table[my_syscall_num]);//保存原始系统调用的地址
  35. orig_cr0 = clear_and_return_cr0();//设置cr0可更改
  36. sys_call_table[my_syscall_num] = (unsigned long)&sys_mycall;//更改原始的系统调用服务地址
  37. setback_cr0(orig_cr0);//设置为原始的只读cr0
  38. return 0;
  39. }
  40. asmlinkage long sys_mycall(void)
  41. {
  42. printk("This is my_syscall!\n");
  43. return current->pid;
  44. }
  45. static void __exit exit_addsyscall(void)
  46. {
  47. //设置cr0中对sys_call_table的更改权限。
  48. orig_cr0 = clear_and_return_cr0();//设置cr0可更改
  49. //恢复原有的中断向量表中的函数指针的值。
  50. sys_call_table[my_syscall_num] = (unsigned long)anything_saved;
  51. //恢复原有的cr0的值
  52. setback_cr0(orig_cr0);
  53. printk("call exit \n");
  54. }
  55. module_init(init_addsyscall);
  56. module_exit(exit_addsyscall);
  57. MODULE_LICENSE("GPL");
-------------------------------------------------------
5,将模块插入成功后,剩下的就是在用户态下测试是否成功了。

添加linux系统调用的两种方式的更多相关文章

  1. Mac Item2 SSH免密登录Linux 服务器的两种方式

    转自http://blog.csdn.net/jobschen/article/details/52823980 mac ssh登录linux服务器 的两种方式: 个人推荐第二种,zsh方式,只需要把 ...

  2. Linux 服务管理两种方式service和systemctl

    Linux 服务管理两种方式service和systemctl 1.service命令 service命令其实是去/etc/init.d目录下,去执行相关程序 # service命令启动redis脚本 ...

  3. 不停mysql服务添加从库的两种方式

    现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. ...

  4. Linux安装jdk(两种方式)

    最近在研究大数据方面的东西,业务场景是从设备采集数据经过处理然后存放DB. 建设上面的环境第一步肯定是安装jdk,所以和大家一起学一下基本知识centos7.5安装jdk1.8. 安装jdk有两种方法 ...

  5. Linux内核分析-两种方式使用同一个系统调用

    实验部分 根据系统调用表,选取一个系统调用.我选得是mkdir这个系统调用,其系统调用号为39,即0x27 由于mkdir函数的原型为 int mkdir (const char *filename, ...

  6. Android------Button 添加声音效果(两种方式)

    我在先前的案例<Android 的底部导航栏 BottomNavigationBar>中添加以底部 的4个按钮切换添加声音 下来看看案例效果图 使用添加依赖 compile 'com.as ...

  7. iOS UIWebview添加请求头的两种方式

    1.在UIWebviewDelegate的方法中拦截request,设置request的请求头,废话不多说看代码: - (BOOL)webView:(UIWebView *)webView shoul ...

  8. linux 安装mysql两种方式

    yum -y install gcc gcc-c++ ncurses-devel cmake  bison   zlib    zlib-devel libxml  openssl   dtrace ...

  9. Android Studio添加aar依赖的两种方式

    1 android{ repositories { flatDir { dirs 'libs' } } } dependencies { implementation fileTree(include ...

随机推荐

  1. redis竞汰数据同步问题解决

    Redis 面试的时候遇到过问Redis是如何解决“竞态条件”的,相关知识点总结一下. 乐观锁 所谓竞态条件,举个例子,一个代表点击数的数值hitcount,每个客户点击一次则+1. 没有事务的时候, ...

  2. compass Errno::EACCES on line ["897"] of C: Permission denied

    具体原因不清楚,应该是与新版的sass有关. 目前的处理方法就是安装原来的版本 gem uninstall compass gem uninstall sass gem install sass –v ...

  3. android中通过intent传递复杂数据

    android中在各个service或者acitivity之间可以通过Intent来传递一些数据,intent原生直接提供了一些简单数据类型的数据的传递,使用起来也很方便,比如int boolean ...

  4. Mac/Linux如何查找应用所安装路径

    Linux.Mac中查看某 个软件的安装路径(地址)有时显得非常重要.比如某个文件的快速启动项被删除,或者你要建立快速启动项,或者想删除. 添加安装文件等等,很多地方都要用到查案文件安装路径的命令. ...

  5. Docker孵化的5个开源项目

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/81977243 回想过去短短 ...

  6. “failed to excute script xxx” PyInstaller 打包python程序为exe文件过程错误

    在使用PyInstaller打包python程序,打包命令为: pyinstaller -F -w -i manage.ico yourpyfile.py 顺便说一下几个参数的作用 -F:是直接生成单 ...

  7. [Math] Unconstrained & Constrained Optimization

    粘贴两个典型的例子,只是基础内容,帮助理解. (1) Solution: (2) Solution:

  8. HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别

    HashMap 是否是线程安全的,如何在线程安全的前提下使用 HashMap,其实也就是HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的 ...

  9. Nuxt.js项目实战

    感悟 经过几个周六周日的尝试,终于解决了服务端渲染中的常见问题,当SEO不在是问题的时候,或许才是我们搞前端的真正的春天,其中也遇到了一些小坑,Nuxt.js官方还是很给力的,提issue后很积极的给 ...

  10. k8s(1)-使用kubeadm安装Kubernetes

    安装前准备 1. 一台或多台主机,这里准备三台机器 角色 IP Hostname 配置(最低) 操作系统版本 主节点 192.168.0.10 master 2核2G CentOS7.6.1810 工 ...