精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>电脑技术>>● FreeBSD>>FreeBSD 核心探讨 (cool!)>>FreeBSD核心探讨.6.驱动程序篇

主题:FreeBSD核心探讨.6.驱动程序篇
发信人: liangvy()
整理人: hahalee(1999-04-09 17:30:30), 站内信件
(翻译:liangvy.icewolf.lenn)[[email protected]]
[版权所有,不得书面出版]

2。2。3mount根目录之前的处理概要
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也可以,而且这样可以获得更高的效率,这样看起来,就象实际上
        是连续操作了。
        (代续)
--

--
※ 来源:.网易 BBS bbs.netease.com.[FROM: www2.dt.sanyo.co.jp]

[关闭][返回]