|
FreeBSD 核心 (2)
|
|
c nfs/nfs_vnops.c
spec_vnodeop_opv_desc miscfs/specfs/spec_vnops.c
umap_vnodeop_opv_desc miscfs/umapfs/umap_vnops.c
union_vnodeop_opv_desc miscfs/union/union_vnops.c
------------------------------------------------------------------------
这个基础上,spec_vnodeop_opv_spec里描述的操作群就是device driver
interface的东西!!
( 本小节完,待本岛主有空再继续 )
FreeBSD核心探讨.6.驱动程序篇
2.3 mount根目录之前的处理概要
mount根目录的时候,main()(@kern/init_main.c)的初始化的过程从xxx_vfs_mountroot()
(@kern/init_mail.c)被调用开始。如果处理过程正常,就对rootvp设定包含了root的
v-node。
。main()的初始化过程中,configure()(@autoconf.c)被调用。在这个,io设备
初始化完了后,就转移到如下两个变量的地址:一个是mountroot,是处理mount的routine,
另一个是mountrootvfsops,是处理虚拟文件系统的routine。在本机磁盘中,就进入变量
rootdev所指定的disk号中。这里就是,假定本机磁盘
mountroot vfs_mountroot
mountrootvfsop &ufs_vfsops
rootdev boot disk number
。xxx_vfs_mountroot()(@kern/init_main.c)
运行(*mountroot)(mountrootvfsops)后,就指明了root file system的mount.
。vfs_mountroot()(@kern/vfs_conf.c)
管理mount的了文件系统的信息的struct mount(@sys/mount.h),对它进行确认
,然后设定传递过来的对虚拟文件系统的操作群(&ufs_vfsops),才进行"root"
标记。根据VFS_MOUNT(mp,...)进行mount这个虚拟文件系统。mount成功后,就
追加file system的list。这里,由于传递了&ufs_vfsops,就可以调用
ffs_mount()(@ufs/ffs/ffs_vfsops.c)
。ffs_mount()
首先调用bdevvp()(@kern/vfs_subr.c),进行VBLK类别,spec_vnodeop_p
(@misc/specfs/spec_vnops.c) v-node操作,保证设定了驱动号的rootdev的
v-node的最新信息,然后设定rootvp。最后,通过ffs_mountfs()调用进行实际
的mount rootvp操作。
。ffs_mountfs()
各种各样的检查完了后,调用VOP_OPEN(),打开rootvp的v-node。在这里,如果
v-node的v_op成员在spec_vnodeop_p存在的话,就调用spec_open()(@misc/
specfs/spec_vnops.c)。
.spec_open
由于VBLK里包含v-node的种类,从v-node指定的device号取得major的
号,调用对应driver的XXopen() routine
续上,由VOP_IOCTL()(还是的通过spec_ioctl()(@misc/specfs/spec_vnops.c))
可以得到partition信息,然后该检查super block的内容。正确的话,就在struct
ufsmount(@ufs/ufs/ufsmount.h)设定unix file system,这样处理过程就完了。
2.2.4 struct buf 和block的输入输出routine
前节的ffs_mountfs()提到使用bread()(@kern/vfs_bio.c)读出partition的
super block。这个接口函数很快就会解释。它主要用于读取block型的device到
kernel内部的buffer中。
bread(struct vnode *vp, /*(in)输入对象的v-node*/
daddr_t blkno, /*(in)block号*/
int size, /*(in)读出的byte数量,block长的倍数*/
struct ucred * cred,/*(in)权限信息*/
struct buf ** bpp)/*(out)存储读来的data*/
同样的buffer link后的block输出的子程序是bwrite()。
bwrite(struct buf *bp) /*(out)可以输出的struct buf*/
两者之间共同的地方就是struct buf(@/sys/buf.h),它用于io处理中给device driver
做桥梁作用的数据结构。它记录了v-node,io的区别,可以io的block位置/byte数,存
储实际data buffer的address,io处理的进展情况等。
bread则通过getblk()对block输入的结构struct buf进行操作。getblk()调用在核心
管理buffer link和返回指定大小的block的struct buf。这个(缓冲区)内容在目的
block是否存在与指定v-node的指定位置block是否已经构成缓冲环有关。struct buf
里面有一个标志位,当缓冲环内容变化是,这个标志位就会改变。bread()根据这个
flag判断block是否已经缓冲,如果已经完成,它就终止退出。如果不是这样,则在
struct buf的mark里面标志,然后调用VOP_STRATEGY()。在v-node登记的strategy
routine记录了io处理的过程,所以bread()当实际的处理完了后,就调用biowait()
进入等待状态。然后,就转移到别的进程A。io处理完了后,调用biodone(),进程A
也可以继续进行。还有,调用bread()的一边,当完成操作后,就调用brelse(),在
里面对struct buf的flag重新设置,让它对别的程序开放。
bwrite也是同样的通过VOP_STRATEGY()对io处理要求进行登记,同时也调用biowait()
进入等待状态,同样,当实际操作完了后,也设置flag进行复位,使得其他程序可以
使用io,当空闲的时候,io就挂起,转向其他进程处理。
进程等待进入的时候,当然不限于只是调用biowait()。在bread()或者bwrite()之前,
系统必须分配足够的资源供它使用,比如一些缓冲区等。当进行实际io时候,1个block
也可以,多个block也可以,而且这样可以获得更高的效率,这样看起来,就象实际上
是连续操作了。
(代续)
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(
上一页 [1] [2] [3] [4] 下一页
|
| 上一篇:FreeBSD 核心 (1) 下一篇:FreeBSD内核定制参考 |