Linux环境下字符设备驱动开发入门
来源:互联网 发布:北京淘宝童模招聘 编辑:程序博客网 时间:2024/05/20 05:57
前言
这篇文章主要总结了我学习嵌入式系统中,一个字符设备驱动的构建和运行过程。这篇总结中我会尽量简洁地告诉你在Ubuntu(Linux)中字符设备驱动的编程方式,一个简单的模块用C如何进行构建,并且如何将它作为内核模块动态地加载和卸载,你能够看到这个字符驱动设备在系统日志中的记录。
在这篇当中,我们会将重点放在程序结构和编译运行加载过程,关于字符设备和环境等等将不做详细介绍。
主要内容
- 字符设备驱动的主要结构和编写
- 字符设备驱动的Makefile编写
- 将驱动作为动态模块进行加载
为了简洁明了,我们以一个加载时和卸载时候打印hello的驱动为例进行说明。
字符驱动的结构
- 首先需要声明该设备的主设备号
TEST_MAJOR
和设备名称drv_name
。 - 其次实现关于设备的函数,一般包括
open()
,release()
,read()
,write()
,后面用户操作的时候,kernel实际会调用 这些函数。 - 声明一个
file_operation
结构体,然后使用标记化结构初始化语法进行初始化(关于这个可以参考标记化结构初始化,C Primer Plus中也有较为详细的介绍,请参考结构相关章节)。这一步的操作将结构体中的内容和我们的实现函数进行一次“绑定”。 - 实现
init()
函数,并且在函数内使用register_chrdev(TEST_MAJOR,drv_name,&chardev_fops)
函数进行设备号的注册;
实现exit()
函数,并在函数内部使用unregister_chrdev(TEST_MAJOR,drv_name,&chardev_fops)
函数对设备进行注销操作。 - 最后记得使用
module_init(test_init);module_exit(test_exit);
将设备看作模块进行注册注销关联。
下面我们将给出这个hello.c程序:
#include<linux/module.h>#include<linux/kernel.h>#include<linux/init.h>#include<linux/fs.h>#define TEST_MAJOR 233 //定义主设备号static char drv_name[] = "test"; //定义主设备名 //自己实现的打开函数static int test_chardev_open(struct inode *inode,struct file *file) { printk("open major=%d, minor=%d\n", imajor(inode), iminor(inode)); return 0;}//自己实现的释放函数static int test_chardev_release(struct inode *inode,struct file *file ){ printk("close major=%d, minor=%d\n", imajor(inode), iminor(inode)); return 0;}//标记化结构体初始化static struct file_operations chardev_fops={ .owner = THIS_MODULE, .open = test_chardev_open, .release = test_chardev_release,};//初始化注册设备static int __init test_init(void){ printk("Hello Mr.Bubbles\n"); if(register_chrdev(TEST_MAJOR,drv_name,&chardev_fops)) { printk("fail to register device \n"); return -1; } return 0;}//注销设备static void __exit test_exit(void){ printk("Goodbye,Mr.Bubbles!\n"); unregister_chrdev(TEST_MAJOR,drv_name);}//进行关联module_init(test_init);module_exit(test_exit);//声明许可证MODULE_LICENSE("GPL");
字符驱动的Makefile文件
我们直接放上Makefile文件的代码:
obj-m := hello.oKERNELDIR := /lib/modules/4.4.0-22-generic/buildPWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean: rm –rf *.o *~ core .depend . *.cmd *.ko *.mod.c .tmp_versions
在这里我们需要声明以下内核所在的位置,因为我们的驱动将作为一个模块单独编译进内核中去。-C
进入内核目录,M
返回当前模块的目录。关于详细的驱动Makefile中的细节,给出以下的参考文章:
1. Linux下的makefile编写详解
2. Linux内核模块的编译基础知识
3. linux设备驱动makefile入门解析
4. 内核 __init与__exit
5. linux内核及驱动开发中有关__init,__exit和__initdata的用法
编译、加载和卸载模块
我们的驱动编写工作可以说是进入了收尾阶段,下面就需要进行编译和加载。首先这是未编译的状态:
然后我们执行make
指令:
这里我们可以清楚的看到shell进入了内核执行了makefile然后回到当前目录生成ko文件。这个就是我们的模块文件。在当前目录下我们执行insmod
指令就可以将我们的模块动态进行加载。
这里的效果我们需要通过系统日志才能看到,打开/var/log/syslog文件就可以看到(中间的“Hello,Mr.Bubbles”):
然后我们尝试进行卸载,使用rmmod
就可以卸载当前的模块 :
最终模块被成功卸载,显示“Goodbye,Mr.Bubbles!”字样。
小结
虽然是考试前的复习,但是如果不自己动手亲自写一下的话是体会不到其中的乐趣的,当然这个介绍只是一点简单的总结,很多细节都被略过了,要对其有更好地了解还需要自行补更多的知识,当然,Embedded System还有很多好玩的东西,希望这篇可以帮助我回顾,同时与大家共勉。
欢迎提出各种意见和建议,共勉。
对了,以前扒数据就发现有直接粘贴不贴出处的,这样可不好啊,这些人注意下0_0
- Linux环境下字符设备驱动开发入门
- linux驱动开发-字符设备
- linux字符设备驱动开发
- LINUX设备驱动开发入门之环境搭建
- Linux内核开发之简单字符设备驱动(下)
- Linux内核开发之简单字符设备驱动(下)
- Linux 驱动开发-字符设备驱动
- 字符设备驱动 - linux驱动开发
- 【驱动】linux设备驱动·字符设备驱动开发
- Linux设备驱动入门----globalmem字符设备驱动
- Linux设备驱动入门----globalmem字符设备驱动
- Linux字符设备驱动入门(一)
- linux字符设备驱动入门模版讲解
- Linux设备驱动开发详解--笔记6--字符设备驱动
- Linux设备驱动开发学习(1)--字符设备驱动
- Linux字符设备驱动程序开发(1)-使用字符设备驱动
- linux下字符设备驱动详解
- linux下的字符设备驱动
- 代码设置图片不渲染
- 如何修改命名空间
- 用phpmyadmin导入大容量.sql文件
- ios切图规范
- 个人资料上传头像模块,拍照+图库+图片剪裁+圆形头像
- Linux环境下字符设备驱动开发入门
- IOS开发中的实用技术使用注意点
- Java注解
- java.sql.SQLException: Wrong number of parameters: expected 0, was given 1 Query:
- React Native运行官方例子----组件集合
- 交通灯控制系统
- 行内框盒子模型
- Java内存分析
- UML 基础/类图/可视化建模