• linux内核可加载模块编程简单入门


    1.linux源代码结构 fs:file system文件系统,usr/src/linux:linux内核头文件,mm:内存管理代码

     2.下载linux内核代码  可自己选择版本,这里是比较老的版本适合小白入手(eg:我用的是0.1x,点击直接下载即可) 

    http://oldlinux.org/Linux.old/kernel/

    https://mirrors.edge.kernel.org/pub/    两个网址都可以下载

     3.Linux系统的整体结构

     4.可加载的内核模块,就是linux使用C语言写的,由于C语言是模块化编程的,添加模块很麻烦,所以为了给Linux添加模块,于是诞生了LKM,就是可以使使用户随时添加内核模块到内核,也可以随时卸下,不和内核建立捆绑,我们今天编写的内核程序就是基于这个原理的.

     5.内核模块的编写,简单例子,只使用一个内核函数printk();printk在内核源码中用来记录日志信息的函数,只能在内核源码范围内使用。用法和printf非常相似

    创建k.c文件命令:sudo vim k.c   (sudo是切换到root用户,如果你已经是root了,就不用sudo了),另外请注意,内核模块只能root运行,普通用户无法让内核模块运行,

    所以,得切换到root模式,su -  root,但是在root下操作要小心啊!!!

    //k.c
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    //module.h包含了对模块的版本控制
    //kernel.h包含了常用的内核函数
    //init.h包含了宏__init和__exit
    /*
     * 模块的初始化函数 lkp_init()
     * __init是用于初始化的修饰符
     */
    static int __init lkp_init(void)
    {
      //<1>是输出的级别,表示立即在终端输出
      printk("<1>hello,Kernal!...
    !");
      return 0;
    }
    /*
     * 模块的退出和清理函数 lkp_exit()
     */
    static void __exit lkp_exit(void)
    {
      printk("<1>Goodbye,world!...
    ");
    }
    
    module_init(lkp_init);
    module_exit(lkp_exit);
    /*
     * 模块的许可证声明GPL
     */
    MODULE_LICENSE("GPL");

     补充知识点:

    printk相比printf来说还多了个:日志级别的设置,用来控制printk打印的这条信息是否在终端上显示的,日志级别的数值小于控制台级别时,printk要打印的信息才会在控制台打印出来,否则不会显示在控制台!内核中有个8个级别.

    #define    KERN_EMERG    "<0>"    /* system is unusable            */
    #define    KERN_ALERT    "<1>"    /* action must be taken immediately    */
    #define    KERN_CRIT    "<2>"    /* critical conditions            */
    #define    KERN_ERR    "<3>"    /* error conditions            */
    #define    KERN_WARNING    "<4>"    /* warning conditions            */
    #define    KERN_NOTICE    "<5>"    /* normal but significant condition    */
    #define    KERN_INFO    "<6>"    /* informational            */
    #define    KERN_DEBUG    "<7>"    /* debug-level messages            */

     6.Makefile文件编写,Makefile文件和k.c文件放在同一个目录下  创建Makefile文件命令:sudo vim Makefile

     引入原因之1:使用GCC的命令进行程序编译时,当程序是单个文件时编译是比较方便的,但当工程中的文件数目增多,甚至非常庞大,并且目录结构关系复杂时,便需要通过makefile来进行程序的编译

    obj-m :=k.o                         #产生k模块的目标文件,这里的k必须和c语言的文件名对应,后缀不同,这里使用了一点shell脚本的知识,读者请百度自行参考
    CURRENT_PATH := $(shell pwd)       #模块当前所在的当前路径
    LINUX_KERNEL := $(shell uname -r)  #linux内核源代码的当前版本,uame -r 查看内核的linux命令
    LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)
                                       #linux内核源代码的绝对路径
    all:
            make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #编译模块,Makefile文件中若一行是命令,必须以tab键开头
    clean:
            make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean   #清理模块

    补充知识:
    obj-m := *.o
    obj-y := *.o
    上面两者的区别在于,前者才会生成ko文件,后者只是代码编译进内核,并不生成ko文件。

    7.编译,使用make命令

    8.查看运行结果及常用命令    注意:在强调一下,root模式下才能运行

    insmod 模块名    #将模块插入内核中,eg:insmod k.ko,把k.ko模块插入内核
    rmmod  模块名    #将模块从内核中删去 eg:rmmod k.ko,将k.ko模块移出内核  o=哦,不是0
    dmesg            #查看模块信息的命令,在make之后,使用就能看到信息
    lsmod            #查看内核模块,可搭配grep使用,eg:lsmod | grep k 查找内核中的k模块

     程序运行结果:

     9.附加知识

  • 相关阅读:
    VS学习笔记2
    VS学习笔记
    分享几个有趣的小程序
    关于类型的转换(抄来的 ,留着,感觉有用。)
    现在觉得IT还挺有意思
    DataGrid 查出一个列 按要求显示格式 例如:操作人(地点)
    WPF DataGrid 列显示0,-1(作废、删除)状态,1,2(支出、收入)类型,操作人(在其他表中),如何转换格式。
    WPF DataGrid中鼠标双击某一列,弹出窗体作为(增加、修改、详细)按钮的快捷键。
    “指定的参数已超出有效值的范围”在【 parameterUpdate.Add(new OracleParameter("STATUS", 0));】报错
    WPF StoreDataSetPaginator
  • 原文地址:https://www.cnblogs.com/nanfengnan/p/14925132.html
Copyright © 2020-2023  润新知