【driver】理解file , file_operations, inode之间的关系

驱动开发基础知识

理解一切皆文件

在unix中,我们对设备的访问最终都会演化成对文件的访问,设备文件往往都存放在/dev的目录下

在terminal中输入ls -l  /dev
//其中字母"b"表示的是块设备。"c"表示的是字符设备

//以sda,sda2,sda3为例,sda表示硬盘,sda2表示硬盘对应的分区
//shell程序使用这些设备进行用户交互,相比于普通文件,设备文件会多出来两个数字,一个是主设备号表示设备类型,另一个是次设备号表示设备的分区
/*设备号是cdev在kernel的唯一标识*/

mknod命令就是在flash创建了一个node节点,unix中一个节点代表一个文件,在一个文件系统中inode节点是唯一的,用来区分不同的文件,inode节点包含了(文件模式,创建时间,user id,group id等,并在文件所在的目录下创建一个目录项),该目录项中包含了之前分配的节点号和文件的名字,最后才被写入flash中

/*
*structure of an inode on the disk
*/
struct ext2_inode {
    __le16 i_mode;
    __le16 i_uid;
    __le16 i_atime;
    __le16 i_size;
    //普通文件,就是文件数据存储的块号
    //设备文件,就是设备的主次设备号
    __le32 i_block[ext2_n_blocks];/*pointer to block*/
}

一言以蔽之,mknod命令将文件名,文件类型和主次设备号等信息保存在磁盘上

上层的进程如何和kernel中的驱动建立联系的呢

sys_open
    do_sys_open
    	getname
    	get_unused_fd_flags
    	do_filp_open
    		path_openat
    			get_empty_filp
    			link_path_walk
    			do_last
    				lookup_fast
    				lookup_open
    					lookup_dcache
    					lookup_real
    						ext2_lookup
    						...
    							inode->i_op = &def_chr_fops

在内核中,进程用task_struct进行描述,其中的files成员指向了一个file_struct的结构变量,该结构中有一个fd_array的指针数据.do_sys_open首先将文件name从用户态copy到内核态,再去调用get_unused_fd_flags获取一个未使用的描述符,,要想获取该描述符,就从fd_array数组中返回一个未使用的描述符,再去调用do_filp_open来构造一个file struct,其中包括了驱动程序操作方法集合的结构体file_operations,该结构体中都是一些函数指针,

/* 
 * do_filp_open()执行流程如下 
*/
该函数调用path_openat执行实际的打开操作
path_openat调用get_empty_filp来快速得到一个file struct,再调用link_path_walk来处理文件路径中除了最后一个分量的前边部分,
/*
* 以/dev/vser3为例
* link_path_walk处理的是/dev这个部分
* do_last处理的是最后一个分量/vser3
*/
do_last会调用lookup_fast在RCU模式下进行快速查找,第一次必然会失败
再去调用lookup_dcache去告诉缓存中查找,第一次也会失败
最后直接去lookup_real去磁盘上去找inode对应的节点

以ext2文件系统为例,ext2_lookup会找到存在flash上的inode节点,inode节点中的f_op指针指向了def_chr_fops,其中的open函数指针指向了chrdev_open,chrdev_open会根据具体的设备号找到内核中的字符设备cdev,并将cdev加载到cdev_map散列表中,并将cdev中关联的file_operations替换最开始file struct中的file operations,基本就完成了设备的open操作
   
为了下一次能够快速的打开文件,内核在第一次打开或者目录时都会去创建direntry目录,它能够保存对应的文件名和相关的inode信息,所有的dentry都会存放在高速缓存中,,这样又有新的文件打开操作是,就会先去高速缓存中去获取inode,没有的话再从磁盘直接search

虽然设备的open操作较为复杂,但是打开后返回了文件描述符,其他的一些系统调用都会通过返回的文件描述符找到对应的文件流指针,最后完成对应方法的调用

int open(struct inode *inode, struct file *filp)
{
	struct device *dev;
	//通过vfs中的inode找到对应磁盘中的inode
	test_dev = container_of(inode->c_dev,struct device,cdev);
	filp->private_data = test_dev;

	return 0
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值