• 在/proc文件系统中增加一个目录hello,并在这个目录中增加一个文件world,文件的内容为hello world


    一、题目

    编写一个内核模块,在/proc文件系统中增加一个目录hello,并在这个目录中增加一个文件world,文件的内容为hello world。内核版本要求2.6.18

    二、实验环境

    物理主机:win7 64bit, i5双核,8G内存

    虚拟机:Vmware Workstation 10.0.2

    虚拟主机: CentOs-5.11,内核2.6.18

    三、实验思路

    在着手解决问题之前,我在网上查阅了一些资料,大多是关于模块的介绍。linux内核采用的是模块化编程,这样可以很容易的添加或删除一个功能,同时可以在内核运行的过程中可以动态的添加功能,这部分功能的代码被称为"模块",我们写的驱动程序就是一个模块。模块在需要使用的时候被加载,不需要的时候可以卸载,这样可以有效的精简系统。对于plinux中的/proc文件系统,它是一个虚拟的文件系统,由内核在运行时动态生成。它提供了内核运行时的配置和状态信息。用户可以通过这些文件来获取、或修改内核的信息。根据题目要求,我们首先要在/proc目录下创建一个hello目录,再在hello目录下创建world文件,文件中的内容为hello world,因此,首先要了解在/proc下创建目录和文件的函数。

    struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent);

    name:文件名

    mode:文件权限

    parent:文件在 /proc 文件系统中父目录指针。

    返回值是创建完成的 proc_dir_entry 指针(或者为 NULL,说明在 create 时发生了错误)。然后通过这个返回的指针来初始化这个文件入口的其他参数,如在对该文件执行读写操作时应该调用的函数。

    四、具体实现步骤

    1.准备工作

    • 查看内核版本

    使用 uname -a 命令查看当前内核版本:

    • 写内核模块需要root权限,升级至root用户

    2. 编写helloworld.c文件

    创建一个文件夹然后创建一个文件helloworld.c

    3.编写Makefile

    接下来编写Makefile文件,该文件与helloworld.c位于同一文件夹下

    4. 运行make

    编写完makefile文件后,保存退出,在makefile文件所在的目录下运make命令

    • 此时出现错误,提示如截图所示
    • 进入错误提示的文件夹下,可以看到红色的build文件,红色表build是一个链接

    • 进一步用ls –l查看其文件属性,build实际指向的是/usr/src/kernels/2.6.18-398.e15-i686

    • 安装之后,仍然报错,于是查看build指向的文件夹

    • 发现我自己的电脑上,对应的文件夹名字如下(这里让我感觉很奇怪,因为实验一开始的时候,用uname -a命令查看内核版本的时候,子版本号是398,但是在系统中,内核对应文件夹名却是402)于是把402改为398

    • 然后就可以进行编译了

    • make之后会生成一些跟模块相关的文件,如下图

    5. 查看.ko文件属性

    用modinfo命令查看make生成的.ko文件的属性

    • 出现错误,提示为找不到命令
    • 解决方案:可以在home目录下查看.bash_profile里的PATH。如果是:PATH=$PATH:$HOME/bin则需要添加成如下:

    PATH=$PATH:$HOME/bin:/sbin:/usr/bin:/usr/sbin

    (参考:http://www.jb51.net/LINUXjishu/32192.html)这个问题也是装系统时只装了精简模式导致的,这导致有些命令不能使用

    • 然后重新启动虚拟机,再次运行modinfo命令就可以查看模块信息了

    6. 加载模块

    接下来用insmod加载模块

    7. 查看所有模块

    模块加载成功后,就可以使用lsmod列出所有的模块,如下图,可以看到helloworld模块

    8. 查看内核日志信息

    用dmesg | tail 输出内核中的日志信息

    可以看到最后一行已经打印出了代码中设定的文本

    9. 打开打开/proc/hello/world

    最后打开/proc/hello/world ,则会输出/proc/hello/world 内容

    至此,模块加载的工作已经完成,下面开始卸载模块

    10. 卸载模块

    用rmmod来卸载模块

    11. 查看当前模块

    再次查看当前的模块,可以看到已经没有helloworld了

    12. 查看打印信息

    查看卸载时的打印信息

    卸载成功,实验结束

    五、总结

        通过这次实验,对Linux系统的模块编程有了一定的了解。一个Linux内核模块主要由如下几个部分组成。

    (1)模块加载函数

    当通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的相关初始化工作。

    (2)模块卸载函数

    当通过rmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块卸载函数相反的功能。

    (3)模块许可证声明

    许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染 (kernel tainted)的警告。

    在Linux内核模块领域,可接受的LICENSE包括"GPL"、"GPL v2"、"GPL and additional rights"、"Dual BSD/GPL"、"Dual MPL/GPL"和"Proprietary"(关于模块是否可以采用非GPL许可权如"Proprietary",这个在学术界和法律界都有争议)。

    大多数情况下,内核模块应遵循GPL兼容许可权。Linux内核模块最常见的是以MODULE_LICENSE( "GPL v2" )语句声明模块采用GPL v2。

        在编译内的时候,如果用Makefile方式的话,要特别注意在Makefile文件中,需要空格的地方都用tab键代替,否则会出现错误。同时,需要将内核源代码所在的目录作为一个参数传递给make命令。

  • 相关阅读:
    构造json响应,重定向响应及终止响应,设置及使用cookies
    Logging模块封装,打印日志
    oracle-数据库的安装与建库
    socket使用实例
    flask的路由、请求方式设置
    Python 元组
    Python 列表的增删改查
    Python 学习之[列表][元组]
    Python学习之[for 循环]
    Python学习之[字符串]
  • 原文地址:https://www.cnblogs.com/scut-linmaojiang/p/4324318.html
Copyright © 2020-2023  润新知