• 为Linux内核增加一个系统调用


    资源下载地址:https://download.csdn.net/download/sheziqiong/85772002
    资源下载地址:https://download.csdn.net/download/sheziqiong/85772002

    题目选择:

    在 Linux 内核中增加一个系统调用,并编写对应的 Linux 应用程序。利用该系统调用能够遍历系统当前 所有进程的任务描述符,并按进程父子关系将这些描述符所对应的进程 id(PID)组织成树形结构显示。

    前期调研:

    关于方法的选择,总体来说,关于添加新的系统调用有两种方法:内核模块法和编译内核法。

    重新编译内核:即在内核源码中,找到包含系统调用号的文件,在其中添加系统调用编号、系统调用跳 转表和相应历程。 添加内核模块:通过将增加系统调用的所有指令封装成一个模块,并在其中实现新的系统调用的功能函 数。

    比较两种方法,我们发现修改内核源码来实现系统调用不仅步骤繁琐,更需要重新编译内核源码, 需要花费较多时间。和修改内核源码相比,添加内核模块的做法更加符合模块化程序的设计思想,设计 思想也相对比较清晰。符合程序设计模块化的思想。操作也更加便捷,因此本实验选择内核模块法来完 成系统调用的新增。

    在本实验中,系统的版本及内核版本如下所示 系统版本和内核版本:

    Ubuntu 14.04.1 LTS

    3.13.0-128-generic 32 位

    设计思路

    整个程序的构思是将增加系统调用号的所有操作在一个文件中体现,之后将该程序运行得到内核模块,将内核模块加载进入系统内核中,之后利用测试程序测试内核模块是否添加成功以及新增的系统调用的功能是否能够实现。

    各模块的说明:

    1、首先我们先进入内核查看系统调用表,找到空余的系统调用号以及系统调用表所对应的内存地址 以用于添加新的系统调用。系统调用表所在路径位 /boot/System.map-3.13.0-128-generic

    从下图可以发现有两个空余的系统调用号 222、223 没有被使用,选择 222 号作为本实验所要求的新的系统 调用号。

    /boot/System.map-3.13.0-128-generic 当我们查看系统调用表时可以看到系统调用表只有“读”权限,因此在添加系统调用号之前首先要对内存区域进行权限修改

    2、关于修改寄存器的权限属性:利用内嵌汇编代码来实现。

    asm(“movl %%cr0, %%eax”:“=a”(cr0)); 是 Linux C 中内嵌的汇编代码,格式位"movl %1,%0":“=r”(result):“m”(input) , “movl %1,%0” 为指令模板,冒号后面是每个操作数对应的 C 表达式(括号的内容)和表达式的说明和限制(引号里的内容)。冒号后第一项对应的是 %0,第二项对应的是 %1。

    3、构造树形图函数

    4、用 sys_mycall 作为新的系统调用,功能是遍历所有进程的并记录任务描述符

    5、将要新增的系统调用号的函数加入到内核中初始化内核

    6、内核模块的加载与卸载

    对于内核构造函数 module_init(init_addsyscall); , 函数原型必须是 module_init() ,括号内的是函数指针.模块析构函数为 module_exit(exit_addsyscall); ,函数原型为 module_exit(); ,此函数在执行卸载内核模块时会被调用。MODULE_LICENSE(“GPL”); 是模块许可声明,是内核程序使用的许可证。

    7、内核模块卸载函数

    遇到的问题及解决方法:

    内核空间与用户空间不能直接访问,如何在用户空间显示内核中的进程树图?

    利用 copy_to_user 函数来实现内核与用户空间的数据交换,copy_to_user(void __user *to,const void *from, unsigned long n),这里的 to 是目标地址即用户空间地址, from 是原地址即内核地址;From 源地址, n 是将要拷贝的数据的字节数。

    对于用户空间中用于存储进程信息的数组的大小应该如何选择?

    数组大小的设置原则是不让数据溢出,首先查看系统所能支持的最大的进程数,本系统中为 14951,但是实际运行的进程数远小于这个数,在实验中,我们选择的数组大小是 1000,查看当前执行的程序数量,80 远小于 1000,故不会存在数据溢出的情况。

    如何让判断系统调用模块添加到了内核中是否成功?利用 dmesg 命令可查看内核中环形缓冲区信息,看输出是否正确。

    程序结果:

    1、加载内核模块:

    可以看到出现了一个 hello 模块

    2、运行测试程序

    3、卸载内核模块

    4、 卸载内核后运行测试程序

    5、利用 dmesg 指令查看输出是否正确


    资源下载地址:https://download.csdn.net/download/sheziqiong/85772002
    资源下载地址:https://download.csdn.net/download/sheziqiong/85772002

  • 相关阅读:
    PTA 1082 射击比赛(Python3)
    Qt::图层框架-图片图层-序列图层-QGraphicsPixmapItem
    (附源码)springboot金融新闻信息服务系统 毕业设计651450
    使用Pytest生成HTML测试报告
    压缩与解压 .tar .tar.gz .tar.bz2 解压 tar.xz
    SAP EWM 交货单暂存区仓位确定(配置实现 / 前台维护)含操作实例
    第三十六篇 Vue中使用Swiper
    02 Shell编程之条件语句
    Effective C++ 阅读笔记 05:实现
    从C语言到C++_36(智能指针RAII)auto_ptr+unique_ptr+shared_ptr+weak_ptr
  • 原文地址:https://blog.csdn.net/sheziqiong/article/details/125458435