zoukankan      html  css  js  c++  java
  • 内核 模块开发

    linux内核的整体结构非常庞大,组件合成分为2种:

    (1):把所有的组件都编译进内核文件,即zImage或bzImage。这种有两个缺点:

      a、生成的内核文件过大。

      b、如果想要添加或删除某个组件,需要重新编译整个内核。

    (2)内核模块机制:需要该组件时,动态地添加到正在运行的内核中。

    内核模块特点:

    (1)模块本身并不被编译进内核文件(ZImage/bzImage).

    (2)可以根据需求,在内核运行期间动态的安装或卸载。

    模块加载函数

    安装模块时被系统自动调用的函数,通过module_init宏来指定,如hello_init。

    模块卸载函数:

    卸载模块时被系统自动调用的函数,通过module_exit宏来指定,如hello_exit。

    模块编译:在linux2.6下编译内核模块,通常使用makefile

    单个源文件(hello.c)编译:

    ifneq ($(KERNELRELEASE),)                //如果KERNELRELEASE不等于空
    
    obj-m := hello.o
    
    else
    
    KDIR := /lib/modules/2.6.18-53.el5/build    //内核源代码路径
    all:
    
        make -C $(KDIR)  M=$(PWD)   modules    //modules:makefile的目标, 
      //-C:进入后面紧跟的目录中使用它的makefile来编译,后面紧跟的是一个目录。
      //M:build文件中要求的,表示内核代码所在。
    clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers endif

    多个源文件(main.c add.c)编译

    ifneq  (($KERNELRELEASE),)
    
    obj-m := hello.o            //内核模块的名字
    hello-objs := main.o  add.o   //hello-objs中hello与模块名字必须一样,如果多个文件,add文件名
    
    else 
    
    KDIR := /lib/modules/2.6.18-53.el5/build
    all:
    
        make  -C  $(KDIR)  M=$(PWD)  modules
    clean:
        rm -f  *.ko  *.o  *.mod.o  *.mod.c  *.symvers
    
    endif

    1.加载insmod  (insmod hello.ko)

    2.卸载rmmod   (rmmod hello)

    3.查看 lsmod

    4.加载modprobe (modprobe hello)

    modprobe如同insmod,也就是加载一个模块到内核。它的不同之处在于它会根据文件

    /lib/modules/<$version>/modules.dep

    来查看要加载的模块,看它是否还依赖于其他模块,如果是,modprobe会首先找到这些模块,把它们先加载到内核。

    1.许可证申明:

    MODULE_LICENSE用来告知内核,该模块遵守的许可证协议,如“GPL”、“GPL v2”。

    MODULE_LICENSE("遵守的协议")

    MODULE_LICENSE("GPL")

    2.作者申明

    MODULE_AUTHOR("作者")

    3.模块描述

    MODULE_DESCRIPTION("模块的功能描述")

    4.模块版本

    MODULE_VERSION("V1.0")

    5.模块别名

    MODULE_ALIAS("别名");

    6.模块参数:通过宏module_param指定保存模块参数的变量。模块参数用于在加载模块时传递参数给模块。

    module_param(name,type,perm)

    name:变量的名称

    type:变量类型,bool:布尔型  int:整形  charp:字符串型

    perm是访问权限。 S_IRUGO:读权限  S_IWUSR:写权限

    如:

    在hello.c中  int a = 9;
    module_param(a,int,S_IRUGO);
    
    
    命令行中输入:insmod  test.ko  a=100   //把100赋给a

    内核符号导出:

    EXPORT_SYMBOL(符号名)

    EXPORT_SYMBOL_GPL(符号名)    //只能用于包含GPL许可证的模块

    如两个模块A、B模块:需在A(定义变量或者函数)中利用EXPORT_SYMBOL(符号名)导出,在B模块中用extern 再声明下。

    uname -r   //查看内核版本

    内核打印:printk。允许根据严重程度,通过附加不同的“优先级”来对消息分类

    printk(KERN_WARNING  "hello world");
    printk("<0> hello world");

    在<linux/kernel.h>中定义了8种记录级别:

    KERN_EMERG     "<0>"     紧急消息

    KERN_ALERT      "<1>"    需要立即处理

    KERN_CRIT        "<2>"    严重情况

    KERN_ERR        "<3>"    错误情况

    KERN_WARNING  "<4>"   有问题的警告

    KERN_NOTICE    "<5>"    正常情况,但仍然需要注意

    KERN_INFO       "<6>"     信息型消息 

    KERN_DEBUG   "<7>"     用作调试消息

    注意:没有指定优先级printk默认使用DEFAULT_MESSAGE_LOGLEVEL优先级,定义在kernel/printk.c中

    如:

    #define DEFAULT_MESSAGE_LOGLEVEL 4

    屏幕上没有打印的消息全在:/var/log/message

    内核打印控制台优先级配置

    在/proc/sys/kernel/printk文件中,cat  /proc/sys/kernel/printk

    6 4 1 7   //console_loglevel    default_message_loglevel   minimum_console_level   default_console_loglevel

  • 相关阅读:
    C# 实现 Snowflake算法生成唯一性Id
    kafka可视化客户端工具(Kafka Tool)的基本使用(转)
    docker 安装kafka
    Model类代码生成器
    使用docker 部署rabbitmq 镜像
    Vue 增删改查 demo
    git 提交代码到库
    Android ble蓝牙问题
    mac 配置 ssh 到git (Could not resolve hostname github.com, Failed to connect to github.com port 443 Operation timed out)
    okhttp
  • 原文地址:https://www.cnblogs.com/Caden-liu8888/p/8280334.html
Copyright © 2011-2022 走看看