• 模块编写流程


    常用的模块操作:

    lsmod将模块列表显示,打印出当前内核中已经安装的模块列表

    insmod安装模块用的时候一定要带名字:insmod  xx.ko
    modinfo 打印一个内核模块的自带信息     modinfo xxx.ko
    rmmod 卸载模块   rm xxx不能加入.ko

    module_init()和module_exit()是模块编程中最基本也是必须的两个函数。

    module_init()是驱动程序初始化的入口点。而module_exit()注销由模块提供的所有功能。

    一个简单的模块函数(.c)
     
    #include <linux/module.h>		// module_init  module_exit
    #include <linux/init.h>			//   __init chrdev_init  __exit chrdev_exit
    
    // 模块安装函数
    static int __init chrdev_init(void)
    {	
    	printk(KERN_INFO "chrdev_init helloworld init
    ");
    	//printk("<7>" "chrdev_init helloworld init
    ");
    	//printk("<7> chrdev_init helloworld init
    ");
    
    	return 0;
    }
    
    // 模块下载函数
    static void __exit chrdev_exit(void)
    {
    	printk(KERN_INFO "chrdev_exit helloworld exit
    ");
    }
    
    
    module_init(chrdev_init);
    module_exit(chrdev_exit);
    
    // MODULE_xxx这种宏作用是用来添加模块描述信息
    MODULE_LICENSE("GPL");				// 描述模块的许可证
    MODULE_AUTHOR("aston");				// 描述模块的作者
    MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
    MODULE_ALIAS("alias xxx");			// 描述模块的别名信息
    

      

    __init,本质上是个宏定义,在内核源代码中就有#define __init xxxx。这个__init的作用就是将被他修饰的函数放入.init.text段中去(本来默认情况下函数是被放入.text段中)。

    整个内核中的所有的这类函数都会被链接器链接放入.init.text段中,所以所有的内核模块的__init修饰的函数其实是被统一放在一起的。内核启动时统一会加载.init.text段中的这些模块安装函数,加载完后就会把这个段给释放掉以节省内存。

    makefile编写

    ubuntu的内核源码树,如果要编译的模块在ubuntu中使用 就打开这2个
    #KERN_VER = $(shell uname -r)
    #KERN_DIR = /lib/modules/$(KERN_VER)/build	
    		
    # 开发板的linux内核的源码树目录
    KERN_DIR = /home/book/per/kernel/linux-2.6.22.6
    #/root/driver/kernel
    obj-m	+= module_test.o//和.c的文件名一致  -m表示编译成模块了  如果是-y即表示编译进内核
    all:
    	make -C $(KERN_DIR) M=`pwd` modules   //-C进入摸个目录  `pwd` modules 作用pwd 是shell命令中的pwd 表示当前路径,记住当前目录,编译完成后再回到当前的目录来,modules表示目标,
    cp:
    	cp *.ko /root/porting_x210/rootfs/rootfs/driver_test
    .PHONY: clean	//.PHONY伪目标 ,把clean生成为伪目标 
    

      

    Makefile分析

    (1)KERN_DIR,变量的值就是我们用来编译这个模块的内核源码树的目录

    (2)obj-m += module_test.o,这一行就表示我们要将module_test.c文件编译成一个模块  -m

    (3)make -C $(KERN_DIR) M=`pwd` modules 这个命令用来实际编译模块,工作原理就是:利用make -C进入到我们指定的内核源码树目录下,然后在源码目录树下借用内核源码中定义的模块编译规则去编译这个模块,编译完成后把生成的文件还拷贝到当前目录下,完成编译。

    (4)make clean ,用来清除编译痕迹

    总结:模块的makefile非常简单,本身并不能完成模块的编译,而是通过make -C进入到内核源码树下借用内核源码的体系来完成模块的编译链接的。这个Makefile本身是非常模式化的,3和4部分是永远不用动的,只有1和2需要动。1是内核源码树的目录,你必须根据自己的编译环境

     编写完成后可以将其置入自己的开发版,insmod rmmod lsmod实验

    模块的安装:

    lsmod再insmod看安装前后系统内模块记录。内核会将最新安装的模块放在lsmod显示的最前面

    insmod与module_init宏。模块源代码中用module_init宏声明了一个函数(在我们这个例子里是chrdev_init函数),作用就是指定chrdev_init这个函数和insmod命令绑定起来,也就是说当我们insmod module_test.ko时,insmod命令内部实际执行的操作就是帮我们调用chrdev_init函数。

    insmod时就应该能看到chrdev_init中使用printk打印出来的一个chrdev_init字符串,但是实际没看到。原因是ubuntu中拦截了,中使用dmesg命令就可以看到了。

     

    补充:

    查看模块的vermagic//模块的内核
    book@book-desktop:~/per/drv$ modinfo module_test.ko
    filename:       module_test.ko
    alias:          alias xxx
    description:    module test
    author:         aston
    license:        GPL
    depends:        built-in
    vermagic:       2.6.22.6 mod_unload ARMv4 
    book@book-desktop:~/per/drv$ ^C
    book@book-desktop:~/per/drv$ 
     
     
    pc上的内核  
    电脑上的内核
    book@book-desktop:~/per/drv$ uname -a 
    Linux book-desktop 2.6.31-14-generic #48-Ubuntu SMP Fri Oct 16 14:04:26 UTC 2009 i686 GNU/Linux
     
    以上就是模块的测试 模块只是一个尚未完成的驱动。
  • 相关阅读:
    ASM认证与口令文件
    asm 兼容性、asm 主要参数管理
    最常见的5个导致 RAC 实例崩溃的问题
    oracle隐含参数的查看与修改
    三种 Failover 之 Client-Side Connect time Failover、Client-Side TAF、Service-Side TAF
    Oracle RAC TAF 无缝failover
    oracle rac的特征
    安装ORACLE时在Linux上设置内核参数的含义
    关于GCC的理解——On the understanding of the GCC
    java中的闭包和回调
  • 原文地址:https://www.cnblogs.com/zhaobinyouth/p/6179760.html
Copyright © 2020-2023  润新知