zoukankan      html  css  js  c++  java
  • 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.附加知识

  • 相关阅读:
    EXTJS 4.2 资料 控件之checkboxgroup的用法(静态数据)
    EXTJS 4.2 资料 控件之Window窗体相关属性的用法
    EXTJS 4.2 资料 控件之textfield文本框加事件的用法
    Entity Framework 学习笔记(一)之数据模型 数据库
    EXTJS 4.2 资料 控件之checkboxgroup的用法(动态数据)
    EXTJS 4.2 资料 控件之Grid 列鼠标悬停提示
    Entity Framework 学习笔记(二)之数据模型 Model 使用过程
    EXTJS 4.2 资料 控件之radiogroup 的用法
    EXTJS API
    vue移动端弹框组件,vue-layer-mobile
  • 原文地址:https://www.cnblogs.com/nanfengnan/p/14925132.html
Copyright © 2011-2022 走看看