2 FreeBSD 核心( 四 )


(代续)



FreeBSD核心探讨.7.驱动程序篇

2.2.5系统调用open()的处理概要
进程通过系统调用read()/write()进行io处理,它由文件描述符指定对哪里进
行i/o,文件描述符是0以上的整数,它在各个进程的struct proc的成员
struct filedesc *p_fd(struct filedesc(@sys/filedesc.h))保留的struct file
((@sys/file.h)进行选择添加 。对struct file,它含有从文件的头的输入输出的byte
位置,输入操作,输出操作,输入输出控制,输入输出的准备状态的检查,执行close
的routine,以及描述io处理对象的信息(v-node,socket,pipe)。系统调用open()
(@kern/vfs_syscalls.c)就是把包含路径信息的v-node找寻出来,为了对它进行io处理,
先要对struct file进行初始化,然后返回文件描述符 。
从路径名查找v-nodehe和io准备操作由vn_open()(@kern/vfs_vnops.c)承担 。
vn_open()通过namei()(@kern/vfs_lookup.c)查找路径对应的v-node名,由VOP_OPEN()
调用不同的v-node定义的准备过程routine 。例如,有如下的处理方法 。
。普通的file/Directory
调用ufs_open()(@ufs/ufs/ufs_vnops.c),检查open的mode
。特殊设备文件
调用spec_open()(@miscfs/specfs/spec_vnops.c)
文字型 调用device driver的open routine
快型 mount的时候出错 。如果不是这样,就调用device driver的
open routine 。

回过头来,namei()的任务是就是,对于指定的路径名,对应于跟目录或者当
前目录的v-node作为起点,通过lookup()(@kern/vfs_lookup.c)进行v-node查找 。
lookup()从路径名开始的v-node(VDIR)开始查找 。找到了的v-node作为新的起点继续进行
查找下一步的要素名,然后得到目的的v-node 。这个时候,根据v-node的不同,目录的检
索方法也就不同 。各个要素的实际检索由VOP_LOOKUP()来做 。

2.2.6系统调用read()的处理概要
open()取得文件描述符后,对它的输入处理,有如下的流程 。指定的文件描述符
的struct file内登记的处理routine有vn_read()(@kern/vfs_vnops.c),vn_write(),
vn_ioctl(),vn_select(),vn_closefile(),v_node
登记的操作routine不能分开使用 。vn_*()里,只有在合适的前缀操作下,才能正确调用 。
read()首先在struct uio(@sys/uio.h)登记进程指定的buffer的位置和长度 。
执行read()后,vn_read()向struct file设定登记的文件的读写位置,然后调用VOP_READ() 。
根据读出来的byte数,读写位置相应增加 。
VOP_READ()的call routine则是与v-node有关,就象下图一样 。

vn_read()
文字型/块型 |
/------------------
| | file/directory
spec_read() ---------ffs_read()-------VOP_READ()
block型 | |
/---------------|char型 |
bread() device driver bread()
| |
spec_strategy() ---------------ufs_strategy() --VOP_STRATEGY()
| | |
| | |
device driver spec_strategy() -------------/
|
|
device driver


。普通的file/directory
调用ffs_read()(@ufs/ufs/ufs_readwrite.c) 。对应指定的读写位置,计算block
的位置,然后用bread()读出来 。读出来的数据送到进程所准备的缓冲区 。从bread()
传递过来的block并不是物理block的位置,而是把file作为block列的一个理论值 。
从理论块到物理块的变换由VOP_STARATEGY()完成 。也就是说,ufs_strategy()先把
文件内位置转化为物理block位置,然后从v-node记录的i-node把表示物理设备的
v-node 去出来,这个VOP_STRATEGY就调用spec()(@miscfs/specfs/spec_vnops.c)
让它进行输入要求 。
。特殊设备文件
通过调用spec_read()(@miscfs/specfs/spec_vnops.c),把它分为文字型和块型两类 。
文字型 调用device driver的输入routine
块型 通过bread()进行输入处理

对文件的系统调用write()的场合也是类似的处理流程(ufs_write()->bwrite()),

推荐阅读