zoukankan      html  css  js  c++  java
  • 3、Linux内核模块学习

    一、内核模块的学习  

    内核的整体框架是非常的大,包含的组件也是非常多,如何将需要的组件包含在内核中呢?选择一,就是将所有的组件全部编译进内核,虽然需要的组件都可以使用,但是内核过分庞大,势必带来效率影响;选择二是,将组件编译为模块,需要的时候,就自行加载进内核,这种就是我们称之为的模块,当模块被加载到内核的机制,不仅控制了内核大小,同时被加载的内核与被编译进内核的部分,功能意义。

      

    3.1、内核的加载与卸载

        将 hello.c 编译为模块,hello.ko,

    insmod hello.ko

        也就可以 hello.ko 模块加载到内核,

        使用 modprobe 也可以加载模块

    modprobe hello.ko

       modprobe 比  install 更加强大,modprobe 加载模块的时候,会将加载模块依赖的模块也进行加载。

    卸载模块:

    rmmod  hello

        实现 模块 hello.ko 的卸载,这里需要注意,卸载的时候,直接写名字就可以了, ko 就不需要了,

       同时,也可以使用 modprobe 卸载模块:

    modprobe -r hello

        modprobe 卸载的时候,会将 hello 模块依赖的其他模块也,卸载掉。

    模块的查看:

    lsmod

        可以查看系统加载的模块,其实lsmod 是通过读取 /proc/modules 文件。

    获得模块的信息:

    modinfo hello(模块名)

        就可以获得模块的信息,包含作者,说明等扽参数。

    3.2、模块模块程序结构

        Linux 内核模块的组成部分是比较的简单,由一下部分组成:

    (1)模块加载函数

    (2)模块卸载函数

    (3)模块许可声明

    (4)模块作者等信息

    3.2.1、模块加载函数

        模块的加载函数,一般是通过 __init 标志声明,一般模块加载函数为:

    static int __init func_for_init(void)
    {
    
        XXXX
        return 0;
    }
    
    module_init(func_for_init);

        通过 module_init 指定函数,这个函数就是模块的加载函数,可以理解为模块的入口,实现的是做一些初始化的工作。 __init 是告诉内核这个函数是特殊函数,实现模块的初始化的功能。

    3.2.2、模块卸载函数

           模块的下载函数是通过 __exit 标识来声明,典型的代码如下:

    static void __exit func_for_exit()
    {
        XXXX
    }
    
    module_exit(func_for_exit);

        module_exit 函数指定了模块的卸载函数,模块的卸载函数实现的是模块加载函数完全相反的功能。

        使用__exit 来修饰模块卸载函数,是告诉内核,这个模块被编译进内核,模块卸载函数 func_for_exit 不会被编译进内核,因为不会再卸载了,干嘛要编译进去呢。

    3.2.3、模块的声明

        模块的声明可以使用 ,MODULE_AUTHOR、MODULE_DESCRIPTION、MODULE_VERSION 等进行声明

    3.3、模块的编译

      将代码编译为模块,需要编写简单的 MakeFile:

    // 单文件 hello.c
    // 多文件 file1.c、file2.c
    
    KDIR = /XXX/XXX/XXX/XX
    
    all :
        make -C $(KDIR) modules
    clean:
        make -C $(KDIR) modules  clean
        rm -rf  modules.order
    
    // 当编译单文件时候
    obj-m += hello.o
    
    // 当多文件编译的时候,
    obj-m := mymodule.o    // 模块的名字,可以自己定义
    mymodule-objs := file1.o file2.o

        KDIR :  指定内核的路径,因为编译的模块,需要内核的环境编译,

        -C : 记得大写,是跳转内核里面进行编译,

        modules : 指定编译的为模块

        obj-m : 指定编译为模块

        单文件的时候,就直接以模块的名字,直接进行编译就可以;

        当多文件编译的时候,编译为模块的名字,模块名字可以自己定义,但是下面一行就,设置为 模块名字-objs  := 各个子文件

  • 相关阅读:
    禁止360开机自动启动
    Google Code注册方法详解 Google Code网盘申请方法
    做程序开发工作,编程思想很重要
    EPP(Eclipse PHP)语法高亮仿EditPlus配置
    2HC32F460(华大)+BC260Y(NBIOT)基本控制篇(自建物联网平台)整体运行测试微信小程序扫码绑定BC260Y(NBIOT),并通过MQTT和单片机实现远程通信控制
    2HC32F460(华大)+BC260Y(NBIOT)基本控制篇(自建物联网平台)整体运行测试Android扫码绑定BC260Y(NBIOT),并通过MQTT和单片机实现远程通信控制
    【面向对象】宽接口、窄接口和访问方法(上)
    重构,小步进行曲
    Java中有些好的特性(一):静态导入
    【读书笔记】设计模式沉思录
  • 原文地址:https://www.cnblogs.com/qxj511/p/5456834.html
Copyright © 2011-2022 走看看