• 内核模块设计


    <内核模块代码>

    1)内核模块内有main()函数

    2)首先编写没内核模块相应的函数功能

    3)内核模块的入口由一个宏(module_init(),module_exit()),来加载和卸载(实际是指明加载函数和卸载函数,这样内核才会认识)

    4)头文件:<linux/init.h><linux/module.h>

    例:

    #include<linux/init.h>

    #include<linux/modules.h>

    static int __init hello_init(void)

    {

    pintk(KERN_WARNING“hello,word ”);

    return 0;

    }

    static void __exit hello_exit(void)

    {

        printk(KERN_INFO“goodby,word ”);

    }

    module_init(hello_int);

    module_exit(hello_exit);

    注意:

    1)一般都会在函数头前加上static

    2)和printf()函数相比,ptintk()打印信息会有一个信息的优先级别,都是以宏的形式出现,如:KERN_WARNING 和KERN_INFO

    3)linux中标志为__init的函数在连接的时候都会放在".init.text"这个区段内,另外所有__init函数在.initcall.init还保存了一份函数指针,在初始化内核的时候利用这些指针调用"__init"函数,在初始化完成之后释放"init"区段。(包括".init.text"和".initcall.init")

    __init和__exit都是Linux中的宏:

    #define __init __attribute__((__section__(".init.text")))

    #define __exit __atrribute__((__section__(".exit.text")))

    <内核模块的Makefile文件>

    格式:

    obj-m := helloword.o

    hello-objs := file1.o file2.o file3.o file4.o

    KDIR= /“path of  linux kernel”(注意:实际编写的时候是没有双引号的)

    all :

    make -C $(KDIR)  M=$(PWD)  modules  ARCH=arm CROSS_COMPLE=arm-linux-

    clean:

    rm -rf  *.o  *.ko *.oder *.symvers

    Makefile文件分析:

    KDIR :用于指定内核代码位置路径

    M:用于指定驱动模块代码位置

    hello-objs:用于多文件的内核驱动模块

    注意:在卸载内核模块的时候,必须在文件系统中的/lib/modules 目录下有指明该模块所对应的内核版本,以表明相互匹配,可以使用命令($(uname -r)),来获取内核版本

    <带参数的内核模块>

    1 #include <linux/init.h>
    2 #include <linux/module.h>
    3 MODULE
    _LICENSE("Dual BSD/GPL");
    4
    5 static char
    *book_name = "dissecting Linux Device Driver";
    6 static int num = 4 000;
    7
    8 static int book
    _init(void)
    9 {
    10 printk(KERN
    _INFO " book name:%s ",book_name);
    11 printk(KERN_INFO " book num:%d ",num);
    12 return 0;
    13 }
    14 static void book
    _exit(void)
    15 {
    16 printk(KERN
    _INFO " Book module exit ");
    17 }
    18 module
    _init(book_init);
    19 module
    _exit(book_exit);
    20 module
    _param(num, int, S_IRUGO);
    21 module
    _param(book_name, charp, S_IRUGO);
    22
    23 MODULE
    _AUTHOR("Barry Song <21cnbao@gmail.com>");
    24 MODULE
    _DESCRIPTION("A simple Module for testing module params");
    25 MODULE
    _VERSION("V1.0");

    1)声明并定义模块参数

    module_param(参数名,参数类型,参数读/写权限)

    2)装载模块时想用户空间向模块传递参数

    insmode 模块名 参数名=参数值  (注意:参数类型可以是int short long byte uint ushort ulong charp bool )

    3)实现该功能的机制

    模块被装载后,会在"/sys/module"目录下出现该模块的名字的目录,当"参数读/写权限"为0的时,表示此参数不存在sysfs文件系统下对应的文件节点,如果当"参数读/写权限"不为0的时,在"sys/module"下对应的模块的名字的目录下将出现parameters目录。该目录下包含一系列的以参数名字命名的文件节点。

    <导出符号>

    1)什么是导出符号

    在Linux2.6的"/proc/kallsyms"文件(存在于内存中)对应着内核符号表,他记录了符号(导出的函数或模块)以及符号所在内存中的地址。

    2)怎么导出符号

    EXPORT_SYMBOL(符号名);

    EXPORT_SYMBOL_GPL(符号名);

    注意:导出的符号可以被其他模块使用,使用之前进行声明一下即可

    3)实例

    1 #include <linux/init.h>
    2 #include <linux/module.h>
    3 MODULE
    _LICENSE("Dual BSD/GPL");
    4
    5 int add
    _integar(int a,int b)
    6 {
    7 return a+b;
    8 }
    9
    10 int sub
    _integar(int a,int b)
    11 {
    12 return a-b;
    13 }
    14
    15 EXPORT
    _SYMBOL(add_integar);
    16 EXPORT
    _SYMBOL(sub_integar);

    在"proc/kallsyms"中的结果如下

     

    <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

  • 相关阅读:
    正则表达式例子
    addevent兼容函数 && 阻止默认行为 && 阻止传播
    addevent
    区分总结innerHeight与clientHeight、innerWidth与clientWidth、scrollLeft与pageXOffset等属性
    setattribute兼容
    随机分配位置
    浏览器类型
    统计一个字符串中相同字符的个数
    Appium发送中文或其他语言的问题
    Appium同时连接多台手机进行测试(多线程)
  • 原文地址:https://www.cnblogs.com/big-devil/p/8589902.html
Copyright © 2020-2023  润新知