zoukankan      html  css  js  c++  java
  • 内核模块编译过程摘要记录

    内核模块编译

    1、实验原理

    Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合。之所以提供模块机制,是因为Linux本身是一个单内核。单内核由于所有内容都集成在一起,效率很高,但可扩展性和可维护性相对较差,模块机制可弥补这一缺陷。

    Linux模块可以通过静态或动态的方法加载到内核空间,静态加载是指在内核启动过程中加载;动态加载是指在内核运行的过程中随时加载。

    一个模块被加载到内核中时,就成为内核代码的一部分。模块加载入系统时,系统修改内核中的符号表,将新加载的模块提供的资源和符号添加到内核符号表中,以便模块间的通信。

    2、编写模块代码

    1)模块构造函数:执行insmod或modprobe指令加载内核模块时会调用的初始化函数。函数原型必须是module_init(),括号内是函数指针

    2)模块析构函数:执行rmmod指令卸载模块时调用的函数。函数原型是module_exit()

    3)模块许可声明:函数原型是MODULE_LICENSE(),告诉内核该程序使用的许可证,不然在加载时它会提示该模块污染内核。一般会写GPL。

    头文件module.h,必须包含此文件;
    头文件kernel.h,包含常用的内核函数;
    头文件init.h包含宏_init和_exit,允许释放内核占用的内存。

    实践代码:

     

    3、编译模块

    编写makefile文件。如下是根据自己情况改写的:

    第一行的name换成你自己写的.c文件名。
    第三行的LINUX_KERNEL_PATH为自己的内核版本对应的内核源码包地址
    make -C $(LINUX_KERNEL_PATH) 指明跳转到内核源码目录下读取那里的Makefile
    M=$(CURRENT_PATH) 表明返回到当前目录继续执行当前的Makefile。 

    编译执行过程我们都会了就不写了。

    4、加载模块

    sudo insmod name.ko

    5、测试模块

    dmesg看内核信息

    6、卸载模块

    sudo rmmod name

    这时用dmesg看内核信息,就会看到写在module_exit()中的输出。(由于我之前做的那个模块还存在,所以打印中也出现了其他模块的内容。)

    7、实现输出当前进程信息的功能

    8、实现读取进程链表的功能

    在上一个代码的基础上,修改代码。

     

    for_each_process()是一个宏,定义如下:

     

    即for循环,从第一个PCB(叫做init_task)开始,顺着next指针遍历。

    修改Makefile,make,insmod。

     

    8.高级模块的编译(替换系统调用模块)——深入项目

    1.首先编写一个代码——系统调用。syscall.c

    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/unistd.h>
    #include <linux/sched.h>
    MODULE_LICENSE("GPL");
    #define SYS_CALL_TABLE_ADDRESS 0xffffffff81801400  //从/proc/kallsyms 提取的 sys_call_table对应的地址
    #define NUM 223  //系统调用号为223
    int orig_cr0;  //用来存储cr0寄存器原来的值
    unsigned long *sys_call_table_my = 0;
    static int (*anything_saved)(void);  //定义一个函数指针,用来保存一个系统调用
    static int clear_cr0(void)  //使cr0寄存器的第17位设置为0(即是内核空间可写)
    {
            unsigned int cr0 = 0;
            unsigned int ret;
            asm volatile ("movq %%cr0, %%rax":"=a"(cr0));  //将cr0寄存器的值移动到eax的寄存器中,同时输出到cr0变量中
            ret = cr0;
            cr0 &= 0xfffeffff;  //将cr0变量的值中的第17位清0,一会将修改后的值写入cr0寄存器
            asm volatile ("movq %%rax, %%cr0": :"a"(cr0));  //将cr0变量的值做为输入,输入到寄存器eax中,同时移动到寄存器cr0中
            return ret;
    }
    static void setback_cr0(int val)  //使cr0寄存器设置为不可写
    {
            asm volatile ("movq %%rax, %%cr0": : "a"(val));
    }
    asmlinkage long sys_mycall(void)  //定义自己的系统调用
    {
            printk("模块系统调用-当前pid:%d, 当前comm:%s
    ", current->pid, current->comm);
            return current->pid;
    }
    static int __init call_init(void)
    {
            sys_call_table_my = (unsigned long*)(SYS_CALL_TABLE_ADDRESS);
            printk("call_init.......
    ");
            anything_saved = (int (*)(void))(sys_call_table_my[NUM]);  //保存系统调用表中的NUM位置上的系统调用
            orig_cr0 = clear_cr0();  //使内核地址空间可写
            sys_call_table_my[NUM] =(unsigned long) &sys_mycall;  //用自己的系统调用替换NUM位置上的系统调用
            setback_cr0(orig_cr0);  //使内核地址空间不可写
            return 0;
    }
    static void __exit call_exit(void)
    {
            printk("call_exit..........
    ");
            orig_cr0 = clear_cr0();
            sys_call_table_my[NUM] = (unsigned long)anything_saved;  //将系统调用恢复
            setback_cr0(orig_cr0);
    }
    module_init(call_init);
    module_exit(call_exit);

    注意:①系统调用表的地址由cat /proc/kallsyms | grep sys_call_table命令得到

    ②将嵌入汇编代码中指令和寄存器名改为64位格式(movl→movq、%eax→%rax)

    2.测试模块功能

    输出Hello和当前进程号pid。

    可见不同时间执行该程序,进程号都不同。

    小结

    做了模块部分的实践,掌握了几个重要的命令操作。知道了如何装载模块等等。我把一些做实验必须用到的素材和步骤记录下来。其他详解能理解的就不赘述了。这方面的实践要不要继续做下去呢,让我看看接下来的课程安排再做计划。看看是要做别的实践任务还是要深入做。

  • 相关阅读:
    November 07th, 2017 Week 45th Tuesday
    November 06th, 2017 Week 45th Monday
    November 05th, 2017 Week 45th Sunday
    November 04th, 2017 Week 44th Saturday
    November 03rd, 2017 Week 44th Friday
    Asp.net core 学习笔记 ( Area and Feature folder structure 文件结构 )
    图片方向 image orientation Exif
    Asp.net core 学习笔记 ( Router 路由 )
    Asp.net core 学习笔记 ( Configuration 配置 )
    qrcode render 二维码扫描读取
  • 原文地址:https://www.cnblogs.com/paperfish/p/5517799.html
Copyright © 2011-2022 走看看