一. 概述
本章节以应用开始访问字符设备为切入点,逐步深入分析字符设备的软件层次、组成框架和交互、如何编写字符设备驱动、设备文件的创建和mdev原理,并对相关接口及涉及到的结构体做一个简要介绍,展示字符设备驱动的全面详情
二. 应用示例
int main(void) {
char buf[10] = {0,};
int fd = open("/dev/led",O_RDWR);
read(fd,buf,10);
memset(buf,1,10);
write(fd,buf,10);
close(fd);
}
三. /dev目录与文件系统
- /dev目录
/dev是根文件系统下的目录文件,/代表根目录,其挂载的是根文件系统yaffs格式,通过读取根目录的这个文件,就能分析list出其包含的各个设备,其中就包含/dev这个子目录。即/根目录是一个文件,其真实存在与flash介质
ls / 命令即会使用/挂在的yaffs文件系系统来读取根目录的内容,然后list出dev(是一个目录),这时还不需要去读取dev这个目录下的文件内容。
cd /dev命令会分析/dev挂载的文件系统的超级块信息,superblock,而不再理会flash 中dev目录下的数据
Notes:
dev是镜像ramfs对应的flash block mount上来的真实flash数据
- /tmpfs文件系统
/dev在根文件系统构建的时候会挂载为tmpfs。tmpfs是一个基于虚拟内存的文件系统,主要使用RAM和SWAP(RAM只是使用物理内存)。以后读取dev这个目录的操作都转到tmpfs的操作,确切的讲都是针对RAM的操作,而不再是通过yaffs文件系统的操作函数集去访问flash介质。
tmpfs文件系统是基于RAM,所以掉电后会消失
Notes:
/dev目录下的设备文件都是每次创建后会消失
/dev目录下的设备文件来源:
在编译过程中制作文件系统时会构建/dev目录,每次在linux系统启动后由设备对应的驱动程序来创建或者mknode手动创建设备文件(/dev/NULL、/dev/console实在制作根文件系统时静态创建)
四. 设备文件的创建
/dev目录下的设备文件基本时通过mdev来动态创建。mdev是一个用户态的应用程序,位于bosybox的工具箱内
创建过程:
驱动初始化或者总线匹配后会调用驱动的probe接口,上述步骤最终均需调用device_create(设备类、设备号、设备名),在/sys/class/设备类目录下生成唯一的设备属性文件(包括设备号、设备名等信息),并且发送uevent事件(KOBJ_ADD、环境变量、路径等信息)到用户空间(通过socket方式),然后通知mdev在/dev下创建相应的设备节点
mdev是一个work_thread线程,收到事件后会分析/sys/class/设备类的对应文件,最终调用mknod动态的创建设备文件,而这个设备文件的主要内容为设备号(这个设备文件对应的inode会记录文件的属性是一个设备文件--其他还包含目录、一般文件、符号链接等)。应用程序open(device_name...)最重要的一步就是通过文件系统接口来获取该设备文件的内容---设备号
如果初始化过程没有调用device_create接口来创建设备文件,则需要手动执行mknod命令来创建设备文件(替代mdev的过程),已暴露设备文件供应用访问