加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 教程 > 正文

Linux设备驱动编程概括

发布时间:2021-12-14 21:45:00 所属栏目:教程 来源:互联网
导读:笔者搞设备驱动有一个多月了,也看了一些程序,前段时间一直很乱,没有办法总结,所以一直没有写文章,昨日热的睡不着,脑袋中却分外清晰,于是整理思路,将一个多月的学习心得总结出来,一方面供广大嵌入式Linux开发者参考,一方面稳固自己的知识。 我将分

笔者搞设备驱动有一个多月了,也看了一些程序,前段时间一直很乱,没有办法总结,所以一直没有写文章,昨日热的睡不着,脑袋中却分外清晰,于是整理思路,将一个多月的学习心得总结出来,一方面供广大嵌入式Linux开发者参考,一方面稳固自己的知识。
 
我将分为5篇文章去总结,这是第一篇,因为Linux中的驱动都是以模块的方式加载到内核中的,所以学习模块编程必须成为第一步。
 
各种官方的介绍此处略过,我们先来看一个最简单的模块实例:helloworld!
 
#include <linux/kernel.h>   
#include <linux/init.h>   
#include <linux/module.h>   
  
  
MODULE_LICENSE("GPL");      //申明LICENSE,不写编译会有警告,所以还是写了吧   
  
/*-----------------------------------------------------------------------------
  函数名:      hello_init                                                                          
                                                                                                          
  参数:           void                                                                                                      
  返回值:      <SPAN style="WHITE-SPACE: pre"> </SPAN> int                                                                                                                                                                                                
  描述:       模块初始化函数,在安装模块时候执行                                                                                          
                                                   
 *-----------------------------------------------------------------------------*/  
static int __init hello_init(void)    
{  
    printk("hello world!--It is kernel speakingn");        //类似于printf,是在内核中使用的打印函数   
    return 0;  
}  
  
/*-----------------------------------------------------------------------------
  函数名:      hello_exit                                                                          
                                                                                                          
  参数:           void                                                                                                      
  返回值:          <SPAN style="WHITE-SPACE: pre"> </SPAN>void                                                                                                                                                                                                
  描述:       模块退出函数,在安装卸载时候执行                                                                                          
                                                   
 *-----------------------------------------------------------------------------*/  
  
static void __exit hello_exit(void)   
{  
    printk("Goodbye!Kerneln");  
}  
  
module_init(hello_init);  
module_exit(hello_exit);  
这个函数已经简单的和helloworld一样简单清楚和可爱了,我只做几点说明:
 
1.大家可以看到模块函数没有main函数,只有init函数,一般在模块编译好之后,会执行insmod命令,这是就会调用module_init函数中注册的初始化函数,也就是hello_init函数!同样在模块用完之后,我们通常会执行rmmod以移除模块,这时候就会调用module_exit中注册的函数,也就是 hello_exit 函数。
 
2.__init和__exit,(注意是两个下划线)这个是两个关键字,目的是告诉内核,在模块init的时候开辟内存,在模块退出的时候释放内存,如果不加这两个关键字,模块卸载的时候就不会释放内存,这就造成了内存的浪费。
 
Makefile:
 
有了程序,下面就要编译程序了,模块的编译方法和编译程序可不一样,下面提供一个Makefile模板,这个时代已经不是从无到有的用手敲代码了,而是在模板的基础上改动,这样才能提高效率:
 
obj-m:=hello.o    
  
CURRENT_PATH :=$(shell pwd)  
#VERSION_NUM  :=$(shell uname -r)   
#LINUX_PATH   :=/usr/src/linux-headers-$(VERSION_NUM)   
LINUX_PATH   :=~/by700/linux-2.6.30-atmel9260  
  
all :  
    make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules   
  
.PHONY :clean  
clean:  
    rm -rf *.o *ko  
我也做几点说明:
 
1.object -m :=hello.o,是要编译的模块的目标文件对应于hello.c,所以需要根据具体情况修改
 
2.对于这个模板我们第二个要修改的地方就是内核目录,大家看到我用#把两句话隐藏掉了,这个方便开启PC和目标      板之间的切换:
 
对于PC端,一般编译好的内核源代码就放在我#号隐掉的目录下,只要#号去掉,同时把第二个LINUX_PATH隐掉,就可以直接使用这个Makefile文件,这个不难,主要是目标板上的模块,我调试了两天才调试通
 
对于目标板(笔者的是at91)的芯片,LINUX_PATH这个目录就需要调整了,因为我们在PC机上编译目标板的内核代码由读者自己选定,我这个暂时就选定在如代码中的目录下。
 
特别注意,这个目录一定要和目标板烧写的镜像是一致的,否则会出现内核和模块不匹配的错误,笔者就是被这个错误改了内核代码,结果越来越多错误,最后请教高手才解决的
 
我在这里用的交叉编译环境是:arm-angstrom-linux-gnueabi-
 
所以在执行的make的时候,要执行如下:make ARCH=arm CROSS_COMPILE=arm-angstrom-linux-gnueabi-
 
结果如下:
 
root@at91sam9260ek:/mnt/hello# insmod hello.ko  
hello world!--It is kernel speaking  
root@at91sam9260ek:/mnt/hello# lsmod  
Module                  Size  Used by    Not tainted  
hello                   1120  0   
root@at91sam9260ek:/mnt/hello# rmmod hello   
Goodbye!Kernel  
root@at91sam9260ek:/mnt/hello# lsmod  
Module                  Size  Used by    Not tainted  
root@at91sam9260ek:/mnt/hello#   
内核模块可以加载的文件是.ko后缀名的!

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读