int(*dir_notify)(struetfile*filp, unsignedlongarg);//仅对文件系 统有效,驱动程序不必实现 int(*floek)(struetfile*,int, streutfileloek*); 可以看到结构体 file_叩erations包含了很多操作,但是在实际设备驱动程序中 只会用到其中很少一部分。 4.1.2 file结构 file结构也是设备驱动中非常重要的数据结构,它只出现在内核代码中,file结构 代表一个打开的文件。在file结构体中很多成员并不对设备驱动程序有用,所以在这 里只介绍一些常用的重要成员: Structdentry*f一dentry;//该成员是文件对应的目录项结构 Structfile_oPerations*f--oP;//该成员是定义与文件相关联的操作 unsignedintf_flags;//该成员是文件标志,表示文件的权限类型 mode_t几mode;//用于确定文件的读写权限 loff_tf_pos;//用来确定当前的读写位置 void*PriVate_data;//跨系统调用时间保存状态信息的资源 file结构体有内核在调用open操作时创建,并传递给在文件主操作的任何函数, 直到最后关闭。当文件的所有实例都关闭后,内核释放此数据结构。 4.1.3 inode结构 在Linux设备驱动开发中,inode结构表示具体的文件,而file结构表示打开的文 件描述符。对于单个文件来说,可能会有许多表示打开的文件描述符file结构,它 们都指向了单个的inede结构。inode结构中的静态信息取自物理设备上的文件系统, 由文件系统指定的函数填写,它只存在于内存中,可以通过inode缓存访问。虽然每个 文件都有相应的inode结点,但是只有在需要的时候系统才会在内存中为其建立相应的 inode数据结构。 inode结构包含了大量的文件信息,但通常情况下对设备驱动有用的只有两个: devt1rdev;//对表示设备文件的inode结构,该成员包含了真正的设备编号 structcdev*1cdev;//该成员表示字符设备的内核的内部结构,当inode指向一个 字符设备文件时,该字段包含了指向 Structedev结构的指针 inode是非常中要的一个数据结构,它包含文件在系统中被创建的信息。每一个 文件都有一个唯一的inode结构通过inode号码标识。每个inode都给文件提供了一些 很重要的信息。 4.2Linux字符设备驱动的开发 字符设备驱动那个开发的一般流程是: 收集足够的外设硬件信息,如设备数据格式、中断号、采用串口还是并口,对它 们初始化需要做哪些工作,读写设备时涉及到哪些寄存器。 [1〕完成函数init_module和elean_module。init_module包括检查外设是否存 在、初始化该设备涉及到的硬件和数据结构、注册设备以及向系统申请中断。 cleanup_module函数包括对硬件的清零、释放内存、释放中断以及注销设备。 〔2〕完成函数chr_interruPt。修改程序开头定义的中断变量,填入外设的中断 号,读取写入外设的数据并进行简要的处理,读或写操作完成后唤醒其它睡眠的进程。 「3]实现 file_oPerations结构体中的一些重要成员函数,如read、write和 ioetl等。 字符设备驱动模块的一般编程架构如下洲: /*设备结构体*/ struetxxxxdevt struetedevedev xxxxdev; //设备驱动模块加载函数 statieintinitxxxxinit(void) Cdev_init(&xxxx_dev.edev,&xxx_fops); xxxxdev.edev.owner=THISMODULE; //获取字符设备号 if(xxxx_major) { register_ehrdev_region(xxxx_dev_no,1,DEV_NAME); else alloe_ehrdev_region(&xxxx_dev_ ret=edevadd(&xxxx.edev, xxxxdev nO nO O,1,DEV_NAME); l);//注册设备 statievoidexitexit(void) (xxxxdevunregister_ehrdev_region( edevdel(&xxxxdev.Cdev); n。,1);//释放占用的设备号 //注销设备 } module_init(xxxx_init); module_exit(xxxx_exit); 这种结构用alloC_chrdev_region注册设备号,然后用cdev_init初始化一个设 备,最后用cdev_add添加了该设备。 file_。 perations结构与设备关联在一起后,就可以在驱动的架构中补全 file_。PerationS中的函数内容,实现一个完整的驱动架构,如下: statieunsignedintxxxx_open() { } statiCunsignedintxxxx_ioCtl() { } Struetfile_operationsfops={ .owner=THISMODULE, ?OPen=XXXX_OPefl, |