嵌入式Linux驱动程序开发(III)-字符设备驱动程序
浏览:1125 次

姓名:薛少红学号:19020100016学院:电子工程学院
转移自:
【嵌入式牛指南】本文介绍了嵌入式Linux驱动程序开发的字符设备驱动程序的概念和方法
【嵌入式牛鼻子】嵌入式Linux驱动程序开发
【嵌入式牛问题】如何开发嵌入式Linux字符设备驱动程序?
【嵌入奶牛的身体】
Linux中有三种类型的驱动程序:字符设备驱动程序、块设备驱动程序和网络设备驱动程序。
字符设备驱动程序:IO端口的驱动程序,如照明、I2C、SPI、音频等。
块设备驱动程序:内存设备驱动程序,如EMMC、NAND、SD卡、U盘等存储设备
网络设备驱动程序:网络驱动程序,如USB WIFI,使用USB接口,因此属于字符设备,但它可以访问互联网,因此也属于网络设备驱动。
Linuxapp如何调用驱动程序?
在Linux中,一切都是一个文件。成功加载驱动程序后,将在“/dev”目录中生成相应的文件。app可以通过对名为“/dev/xxx”的文件(xxx是驱动程序文件的特定名称)执行相应操作来在硬件上运行。
例如,对于led灯/dev/led的驱动程序文件,app使用open()、close()、write()、read()等函数对该文件进行操作,然后控制硬件。
角色设备驱动程序简介
app在用户空间中运行,Linux驱动程序是内核的一部分,因此驱动程序在内核空间中运行。当我们想在用户空间中操作内核时,例如使用open函数打开/dev/led驱动程序,因为用户空间不能直接在内核上操作,所以我们必须使用一种称为“system call”的方法将用户空间“陷阱”到内核空间中,这样我们才能在底层驱动程序上操作。
如上图所示,从app到特定驱动程序都有相应的功能,例如调用open函数。
在内核部分:Linux内核文件包括/Linux/fs在h中有一个文件。操作的结构是Linux内核驱动的操作函数的集合。(从管理驱动程序文件的名称可知)
1588结构文件_操作{
一千五百八十九
结构模块*所有者;
一千五百九十
loff_t(*llseek)(结构文件*,lof_t,int);
一千五百九十一
ssize_t(*read)(结构文件*,char__user*,size_t,loff_t*);
一千五百九十二
ssize_t(*write)(结构文件*,const char __user*,size_t,loff_t*);
一千五百九十三
ssize_t(*read_iter)(结构kiocb*,结构iov_iter*);
一千五百九十四

ssize_t(*write_iter)(结构kiocb*,结构iov_iter*);
一千五百九十五
int(*迭代)(结构文件*,结构dir_context*);
一千五百九十六
无符号整数(*poll)(结构文件*,结构poll_table_struct*);
一千五百九十七
long(*unlocked_ioctl)(结构文件*,无符号int,无符号long);
一千五百九十八
long(*compat_ioctl)(结构文件*,无符号int,无符号long);
一千五百九十九
int(*mmap)(结构文件*,结构vm_area_struct*);
一千六百
int(*mremap)(结构文件*,结构vm_area_struct*);
一千六百零一
int(*open)(结构索引节点*,结构文件*);
一千六百零二
int(*flush)(结构文件*,fl_owner_t id);
一千六百零三
int(*release)(结构索引节点*,结构文件*);
一千六百零四
int(*fsync)(结构文件*,loff_t,loff.t,int数据同步);
一千六百零五
int(*aio_fsync)(结构kiocb*,int数据同步);
......
1618#ifndef配置_ MMU
一千六百一十九
无符号(*mmap_cabilities)(结构文件*);
1620#结束
1621 };

一
二
三
四
五
六
七
八
九
十
十一
十二
十三
十四
十五
十六
十七
十八
十九
二十
21
22
23
file_操作结构中重要且常用的功能:
在第1589行,所有者拥有结构的模块的指针,该指针通常设置为THIS_module
在第1590行,llseek函数用于修改文件的当前读/写位置。
在第1591行,read函数用于读取设备文件。
在第1592行,写入功能用于将数据写入(发送)到设备文件。
在第1596行中,轮询是一个轮询函数,用于查询设备是否可以执行非阻塞读写。

第1597行,unlocked_ ioctl函数为设备提供控制功能,该功能对应于app中的ioctl功能。
第1598行,compat_Ioctl函数