zoukankan      html  css  js  c++  java
  • linux中模块的构建,传参,和printk函数的简单使用

    静态编译,动态加载
    应用想访问内核需要通过系统调用

    驱动:
    1.模块(打包,加入内核)
    2.内核机制
    3.操作硬件

    在Kconfig里面配置menuconfig的时候,不同的类型会在图形化界面的终端显示不用的配置选项:
    bool CONFIG_HELLO []hello_driver 两态
    tristate CONFIG_HELLO <>hello_driver 三态的 空 * M
    string/int CONFIG_HELLO ()hello_driver 相当于宏替换 (dest)hello_driver ---> 最后在.config中的到的结果就是hello_driver = dest,这个是字符串的格式


    函数模块化编写,可卸载:
    下面是函数:hello_module.c

    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>


    MODULE_LICENSE("GPL"); 模块认证,不写这条语句,最后内核会抱怨的

    static int __init hello_init(void) //通过下面的module,最终内核会解释这条语句为 init_module(),内核执行的时候找的就是这个函数名
    { 函数前面加了--init表示执行一次后对段内容的优化,优化内存,节省空间
    printk("hello_init ! ");
    return 0;
    }


    static void __exit hello_exit(void) //通过下面的module,最终内核会解释这条语句为 cleanup_module(),执行的时候内核找的就是这个函数名
    {
    printk("hello_exit ! ");
    }

    /* module_init:
    * 1. static compile : set "hello_init" to .init section
    * 2. dynamic loadable module: hello_init named init_module
    */
    module_init(hello_init);
    module_exit(hello_exit);

    MODULE_AUTHOR("minj@farsight.com.cn"); 标注一些信息
    MODULE_DESCRIPTION("just for test!");

    对应于上面的makefile的编写:

    MOD_NAME = hello_module

    obj-m = $(MOD_NAME).o

    #KERN_DIR = /home/linux/linux-2.6.35-farsight
    KERN_DIR = /lib/modules/$(shell uname -r)/build

    all:
    make -C $(KERN_DIR) M=$(shell pwd) modules


    clean:
    rm -rf *.o *.ko *.mod.c *.order *.symvers .*.cmd .*versions


    backup:
    tar cvf ../$(MOD_NAME).tar.gz ../$(MOD_NAME)
    cp ../$(MOD_NAME).tar.gz /mnt/hgfs/ubuntu_share


    上面c文件编译过后会生成.ko文件:用下面语句可执行:
    1.make module
    2.sudo insmod hello_module.ko 调用后自动运行驱动程序
    3.sudo dmesg -C 清空之前缓存里面的数据,不然会接着上次打印的结果继续打印,干扰对代码的解读
    4.dmesg 查看代码运行的结果
    5.rmmod hello_module 注意这里不加.ko
    6.lsmod 查看模块

    当想看到hello_module.ko的详细信息的时候,可以用下面的命令:
    modinfo hello_module.ko

    内核函数里面的传参:hello_param.c

    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>


    MODULE_LICENSE("GPL");

    static int m; 想要传参的变量
    static int n;

    module_param(m, int, 0600); 这里是对参数属性的一些定义:int类型,0600是权限,读写权限
    module_param(n, int, 0200);

    static int __init hello_init(void)
    {
    printk("hello_init ! ");
    printk("m = %d : n = %d ", m, n);
    return 0;
    }


    static void __exit hello_exit(void)
    {
    printk("hello_exit ! ");
    printk("m = %d : n = %d ", m, n);
    }

    /* module_init:
    * 1. static compile : set "hello_init" to .init section
    * 2. dynamic loadable module: hello_init named init_module
    */
    module_init(hello_init);
    module_exit(hello_exit);

    MODULE_AUTHOR("minj@farsight.com.cn");
    MODULE_DESCRIPTION("just for test!");

    针对上面函数写的makefile:
    MOD_NAME = hello_param

    obj-m = $(MOD_NAME).o

    #KERN_DIR = /home/linux/linux-2.6.35-farsight
    KERN_DIR = /lib/modules/$(shell uname -r)/build

    all:
    make -C $(KERN_DIR) M=$(shell pwd) modules


    clean:
    rm -rf *.o *.ko *.mod.c *.order *.symvers .*.cmd .*versions


    backup:
    tar cvf ../$(MOD_NAME).tar.gz ../$(MOD_NAME)
    cp ../$(MOD_NAME).tar.gz /mnt/hgfs/ubuntu_share

    编译上面的代码后,传参命令如下:
    1.sudo insmod hello_param.ko m=1234 n=4321
    2.dmesg

    查看传入内核的参数,可用下面的命令查找:
    1.cd /sys/module/hello_param/parametes/
    2.ls
    3.sudo cat 查看你先看的参数

    内核函数的导出:

    一个c文件里面的函数在另一个函数里面调用:
    下面是C文件的脚本,可参考:

    函数提供者:hello_export.c
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>


    MODULE_LICENSE("GPL"); 内核遵循的认证

    void common_func(void) 我们用到的导出函数
    {
    printk("common_func! ");
    }
    EXPORT_SYMBOL_GPL(common_func); //EXPORT_SYMBOL 在这里将函数导出,前面加了GPL表示只有遵循GPL认证的模块可以使用这个函数

    static int __init hello_init(void) 注意这个函数的返回值是int型的
    {
    printk("hello_init ! ");
    return 0;
    }


    static void __exit hello_exit(void) 这个函数的返回值必须是void类型的
    {
    printk("hello_exit ! ");
    }

    module_init(hello_init);
    module_exit(hello_exit);

    MODULE_AUTHOR("minj@farsight.com.cn");
    MODULE_DESCRIPTION("just for test!");


    函数使用者:hello_import.c

    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>


    MODULE_LICENSE("GPL");

    extern void common_func(void); 使用者先申明一下

    static int __init hello_init(void)
    {
    common_func(); 在这里调用了这个函数
    printk("hello_init ! ");
    return 0;
    }


    static void __exit hello_exit(void) 注意前面--exit是优化的作用,一般情况下都会加上的
    {
    printk("hello_exit ! ");
    }

    module_init(hello_init);
    module_exit(hello_exit);

    MODULE_AUTHOR("minj@farsight.com.cn"); 标明作者的信息
    MODULE_DESCRIPTION("just for test!"); 模块的描述

    Makefile的编写:

    MOD_NAME = hello_export

    obj-m = $(MOD_NAME).o
    obj-m += hello_import.o

    #KERN_DIR = /home/linux/linux-2.6.35-farsight
    KERN_DIR = /lib/modules/$(shell uname -r)/build 注意这边路径的编写,因为最后得到的.ko文件需要依赖编译的内核版本,这里解决不同版本的编译运行问题,值得学习

    all:
    make -C $(KERN_DIR) M=$(shell pwd) modules 跳到对应目录执行Makefile


    clean:
    rm -rf *.o *.ko *.mod.c *.order *.symvers .*.cmd .*versions


    backup:
    tar cvf ../$(MOD_NAME).tar.gz ../$(MOD_NAME)
    cp ../$(MOD_NAME).tar.gz /mnt/hgfs/ubuntu_share

    函数执行的时候:先加载提供者,后运行使用者

    sudo insmod hello_export.ko
    sudo insmod hello_import.ko

    然后运行dmesg查看结果

    导出后查看是否成功:cat /proc/kallsyms | grep common_func //下面会看到导出的函数
    lsmod 也能看到函数的信息


    卸载:先卸载使用者,后卸载提供者
    sudo rmmod hello_import
    sudo rmmod hello_export


    内核打印函数printk(),hello_printk.c

    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>


    MODULE_LICENSE("GPL");

    static int __init hello_init(void)
    {
    printk(KERN_INFO "hello_info ! "); //KERN_INFO这里是打印优先级的设置
    printk(KERN_NOTICE "hello notice ! "); //这些权限在内核include/linux/kerner.h里面可以查看
    printk(KERN_ERR "hello_err ! ");
    printk(KERN_ALERT "hello_alert ! ");
    printk(KERN_WARNING "hello_warning ! ");
    return 0;
    }


    static void __exit hello_exit(void)
    {
    printk("hello_exit ! ");
    }

    /* module_init:
    * 1. static compile : set "hello_init" to .init section
    * 2. dynamic loadable module: hello_init named init_module
    */
    module_init(hello_init);
    module_exit(hello_exit);

    MODULE_AUTHOR("minj@farsight.com.cn");
    MODULE_DESCRIPTION("just for test!");

    上面C文件对应的makefile:

    MOD_NAME = hello_printk

    obj-m = $(MOD_NAME).o

    #KERN_DIR = /home/linux/linux-2.6.35-farsight
    KERN_DIR = /lib/modules/$(shell uname -r)/build

    all:
    make -C $(KERN_DIR) M=$(shell pwd) modules


    clean:
    rm -rf *.o *.ko *.mod.c *.order *.symvers .*.cmd .*versions


    backup:
    tar cvf ../$(MOD_NAME).tar.gz ../$(MOD_NAME)
    cp ../$(MOD_NAME).tar.gz /mnt/hgfs/ubuntu_share


    测试执行上面的程序的时候,需要在真正的终端下测试:ctrl+alt+f2进入终端,alt+f7退出终端
    可以更改优先级:列如:
    su
    echo 8 4 1 7 > /proc/sys/kernel/printk //这样在第一个数组设置的对象里面打印的权限在小于8的都能被打印出来
    insmod hello_printk.ko

    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************
    ***************************************************************************************************************************************************************

  • 相关阅读:
    SQL server 事务介绍,创建与使用
    DOM操作系列-01
    JS键盘事件
    Js获取当前日期时间及其它操作
    js中!!的作用
    js == 与 === 的区别[转]
    学习总结--Dom
    css历史
    javascript中 visibility和display的区别
    “==”和Equals区别
  • 原文地址:https://www.cnblogs.com/cnlg/p/4394148.html
Copyright © 2011-2022 走看看