|
 |
栏目导栏 |
|
| |
|
|
|
|
 |
资料搜索 |
|
| |
|
|
|
|
 |
热门文章 |
|
| |
|
|
|
|
 |
最新文章 |
|
| |
|
|
|
| |
| |
|
|
|
| |
| FreeBSD核心入门 作者:(日)大木敦雄 译:Liangvy |
[ 作者: Linux联盟收集 加入时间:2006-06-21 19:30:18 来自:Linux联盟收集
] | |
|
翻译 :Liangvy KCNLinux联盟 E-mail : liangvy@bigfoot.com KCNLinux联盟 原著 :FreeBSD核心入门(日文版) 大木敦雄 KCNLinux联盟 KCNLinux联盟 1.1概述 KCNLinux联盟 FreeBSD可以在PC/AT兼容机器上运行。CPU是i386,i486,Pentium, KCNLinux联盟 Pentium Pro以及其兼容芯片等。 KCNLinux联盟 1.1.1(略) KCNLinux联盟 1,理论地址: 2个13 bit 长+32 bit 长 KCNLinux联盟 2,线形地址:32 bit 长的空间 KCNLinux联盟 3,物理地址:32 bit 长的空间 KCNLinux联盟 1.1.2进程的虚拟空间 KCNLinux联盟 1,text部分 KCNLinux联盟 这部分是执行文件的的text领域,也就是机器语言部分,对于这个 KCNLinux联盟 部分的空间在机器上的物理内存页是共有的,还有,这部分最后的变量 KCNLinux联盟 地址是etext。 KCNLinux联盟 2,data和bss部分 KCNLinux联盟 执行文件的data部分,也就是初始化的数据段和执行文件指定的内 KCNLinux联盟 存变量。内存变量在开始的时候以0填充。这一段空间可以读写。它的 KCNLinux联盟 边界也是以edata和end的地址做结尾。进程的malloc()等内存分配的 KCNLinux联盟 操作的时候,地址的增加方向向bss空间进行。 KCNLinux联盟 3,stack部分 KCNLinux联盟 也就是进程执行的时候的stack空间,这部分空间(从地址的最高位 KCNLinux联盟 开始可以伸缩),其对于物理内存,伸缩程度由核心自动执行。 KCNLinux联盟 1.2 kernel的configure KCNLinux联盟 freebsd的kernel构成文件在/usr/src/sys的目录下面。下面的子目录做一个 KCNLinux联盟 介绍。 KCNLinux联盟 compile 编译核心的目录。 KCNLinux联盟 conf configure的目录。 KCNLinux联盟 ddb 核心调试的sounre code的目录。 KCNLinux联盟 dev 一部分的drivers的source code的目录。 KCNLinux联盟 gnu 浮点运算的仿真以及ex2fs文件系统的source code目录。 KCNLinux联盟 i386 依赖于pc/at机器的目录,以下介绍它的字目录。 KCNLinux联盟 apm suspend一些节电程序。 KCNLinux联盟 boot 不是kernel本身的东西,只是一些怎么从开机到读入kernel KCNLinux联盟 的boot program的source code。 KCNLinux联盟 conf config的一些依赖data。 KCNLinux联盟 isa isa bus的驱动程序类的source code。 KCNLinux联盟 eisa eisa bus的驱动程序类的source code。 KCNLinux联盟 include 对pc/at的一些include files KCNLinux联盟 i386 对pc/at的一些核心code KCNLinux联盟 ibcs2,linux 使各类的os的执行文件在freebsd上执行的code KCNLinux联盟 isofs/cd9660 KCNLinux联盟 cd-rom在unix文件系统上操作的的有关code KCNLinux联盟 kern 核心code KCNLinux联盟 libkern 核心库的source code KCNLinux联盟 miscfs 实现unix文件系统的code KCNLinux联盟 msdosfs 在unix上操作ms-dos文件系统的有关code KCNLinux联盟 net 实现network功能的基本部分code KCNLinux联盟 netatalk KCNLinux联盟 实现appletalk network功能code KCNLinux联盟 netinet 实现internet network功能的code KCNLinux联盟 netipx 实现ipx功能的code KCNLinux联盟 netns 实现ns network的code KCNLinux联盟 netkey 实现网络加密部分的功能的code KCNLinux联盟 nfs 实现nfs服务 KCNLinux联盟 pc98 对于pc98的支持 KCNLinux联盟 pccard 对pcmcia的支持 KCNLinux联盟 pci 对pci bus的驱动程序的source code KCNLinux联盟 scsi 对cd-rom,hard disk,tape 等的scsi驱动程序的source code KCNLinux联盟 sys 独立于机器体系结构的一部分code KCNLinux联盟 ufs unix file system 的支持code KCNLinux联盟 vm 虚拟内存管理的部分 KCNLinux联盟 1.2.1配置的操作----config command KCNLinux联盟 在root权限下,config,make实行后,可以得到简单的kernel。 KCNLinux联盟 *configure file KCNLinux联盟 移动到/usr/src/sys/i386/config看看。 KCNLinux联盟 GENERIC 从cd-rom等安装freebsd的时候对应于defaule kernel KCNLinux联盟 的配置file KCNLinux联盟 LINT kernel组合功能的网罗的的配置file KCNLinux联盟 下面4个是对配置很有必要的的依赖data file KCNLinux联盟 Makefile.386 config生成的Makefile file的template. KCNLinux联盟 devices.i386 对于unix filesystem可能的block型的device KCNLinux联盟 名字和major号的对照表 KCNLinux联盟 files.i386 记录kernel功能组合的基础上,依赖于pc/at KCNLinux联盟 机器的功能名称和各种功能实现的source code KCNLinux联盟 file的名字表。 KCNLinux联盟 options.i386 记录配置项目的表。 KCNLinux联盟 还有,majors.i386是记录对应驱动器的I/O表和major号的一个文件。 KCNLinux联盟 于核心配置没关系。 KCNLinux联盟 对于新的i/o设备,如果要做device driver,对pc/at,要在files.i386(没 KCNLinux联盟 有的话在/usr/src/sys/conf/files)追加相应的行,不然就不能把它加入 KCNLinux联盟 到核心里面。 KCNLinux联盟 追加的格式为 KCNLinux联盟 相对path名 optional device-name device-driver KCNLinux联盟 KCNLinux联盟 对于配置文件,首先,要设置cpu,bus,i/o设备,多少用户等。例如对于GENERIC KCNLinux联盟 machine "i386" KCNLinux联盟 cpu "I386_CPU" KCNLinux联盟 cpu "I486_CPU" KCNLinux联盟 cpu "I586_CPU" KCNLinux联盟 cpu "I686_COU" KCNLinux联盟 ident GENERIC KCNLinux联盟 maxusers 10 KCNLinux联盟 当作为server时候,应该把最大user设置大一点,以提高系统性能。 KCNLinux联盟 下一步,指定options,对于GENERIC KCNLinux联盟 options MATH_EMULATE #support for x87 emulation KCNLinux联盟 options INET #interNETworing KCNLinux联盟 options FFS #Berkeley Fast Filesystem KCNLinux联盟 options NFS #Network Filesystem KCNLinux联盟 ...... KCNLinux联盟 options指定的名字xxx等,如果在/usr/src/sys/conf/options或者在 KCNLinux联盟 /usr/src/sys/i386/conf/options.i386中记载的时候,应在对应的opt_XXX.h中写入 KCNLinux联盟 。没有的话,作为cc命令行的参数定义"-D"在Makefile里面追加。对于XXX的格式应该 KCNLinux联盟 是 KCNLinux联盟 相对path名 optional xxx KCNLinux联盟 下一步,对于config KCNLinux联盟 config kernel root on wd0 KCNLinux联盟 (略) KCNLinux联盟 配置文件剩下的部分应该是bus,i/o等一些硬件配置,一般有controller,device, KCNLinux联盟 disk,tape四类。例如 KCNLinux联盟 controller isa0 KCNLinux联盟 controller eisa0 KCNLinux联盟 controller pci0 KCNLinux联盟 等。 KCNLinux联盟 第二层的device和controller,记录了一些bus设备的连接。ISA的情况是 KCNLinux联盟 device device_name at isa? 参数 KCNLinux联盟 controller controller_name at isa? 参数 KCNLinux联盟 EISA和PCI就相对简单一点: KCNLinux联盟 device device_name KCNLinux联盟 controller controller_name KCNLinux联盟 device_name里指定的设备名是,串口,并口,网络等装置。 KCNLinux联盟 第三层的disk和tape为 KCNLinux联盟 disk disk_name at 控制设备名 drive 号 KCNLinux联盟 tape tape_name at 控制设备名 drive 号 KCNLinux联盟 SCSI接口卡作为第二层的控制装置记录的同时 KCNLinux联盟 controller scbus0 KCNLinux联盟 作为通用的scsi控制设备。因此,对于它的hard disk,tape,cd-rom,mo设备,有 KCNLinux联盟 device sd0 KCNLinux联盟 device st0 KCNLinux联盟 device cd0 KCNLinux联盟 device od0 KCNLinux联盟 等,它可以自动识别和分配号码。 KCNLinux联盟 对于其他的scsi设备,有 KCNLinux联盟 device pt0 at scbus? KCNLinux联盟 这些东西(bus,scsi,i/o),在生成的ioconf.c以及相应的include中有反映。 KCNLinux联盟 configure的最后,不是一些物理设备,而是kernel内部的一些软设置 KCNLinux联盟 pseudo-device 理论设备名 KCNLinux联盟 首先,要考虑以下两个设备: KCNLinux联盟 pseudo-device pty 16 #ttys - can go as high as 256 KCNLinux联盟 pseudo-device log #syslog interface (/dev/klog) KCNLinux联盟 network使用的场合,应该有下面两个 KCNLinux联盟 pseudo-device loop KCNLinux联盟 pseudo-device ether KCNLinux联盟 这种情况下,最好有 KCNLinux联盟 pseudo-device bpfilter 4 #berkeley packet filter KCNLinux联盟 pseudo-device tun 1 #Tunnel driver ( PPP) KCNLinux联盟 想做floppy的时候,要 KCNLinux联盟 pseudo-device vn #Vnode driver ( turns a file into a device) KCNLinux联盟 (代续) KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 FreeBSD核心探讨(翻译)2 KCNLinux联盟 KCNLinux联盟 1.3 FreeBSD boot之前的工作 KCNLinux联盟 1.3.1pc/at机器的boot顺序 KCNLinux联盟 hard disk的最前面的一个block(512byte),叫做master boot recorder(MBR).这 KCNLinux联盟 里有启动限定的program和分区的信息。分区信息是指对于一个区是16byte长,最多 KCNLinux联盟 只能有4个区。16byte的内容是,分区哪里开始,哪里结束。哪种os,能否启动等。对 KCNLinux联盟 于freebsd,安装的时候向MBR写入了boot easy. KCNLinux联盟 磁盘的结构如下图表示: KCNLinux联盟 block Number KCNLinux联盟 #0 #1 #2 ... #14 #15 #16 #17 KCNLinux联盟 ------------------------------------------------------------- KCNLinux联盟 disk no used KCNLinux联盟 label KCNLinux联盟 ------------------------------------------------------------- KCNLinux联盟 <-boot->;|<---------boot2-------------->;| |<--unix file system-- KCNLinux联盟 KCNLinux联盟 FreeBSD用的block#0--#14的15个block里面,含有读入freebsd的程序,bootease KCNLinux联盟 只在block#0里面,在15个block中并没有。它的作用 KCNLinux联盟 。读入mbr,找freebsd的分区 KCNLinux联盟 。读入最初的15个block,到物理内存中0x0001000 KCNLinux联盟 。跳转到相当于block#2的内存位置 KCNLinux联盟 然后,屏幕表示为: KCNLinux联盟 。。。 KCNLinux联盟 。。。 KCNLinux联盟 boot: KCNLinux联盟 (参数说明略) KCNLinux联盟 它的source是/usr/src/sys/i386/boot/biosboot,make之后,生成两个文件: KCNLinux联盟 boot1,boot2分别写入block#1,block#2--#14中。 KCNLinux联盟 一般,一个物理的unix分区理论上可以有8个,比如swap,unix system等。 KCNLinux联盟 boot2部分是boot program,它读入kernel的文件名和option。然后 KCNLinux联盟 。找boot label指定的分区。 KCNLinux联盟 。构造unix filesystem,找指定的kernel KCNLinux联盟 。从开始执行文件,text,data的顺序向物理内存读入。对bss清零。 KCNLinux联盟 。以option的选择,向开始位置跳转。 KCNLinux联盟 1.3.2 kernel的初始化动作 KCNLinux联盟 boot program执行之后,转向kernel的text段开始进行初始化,即先执行 KCNLinux联盟 locore.s的text段。因此是虚拟内存还没有发生作用,locore.s的开始部分必 KCNLinux联盟 须对offset进行补正。locore.s的作用是 KCNLinux联盟 。保存从boot program过来的option KCNLinux联盟 。设定虚拟的stacker KCNLinux联盟 。检测cpu的module KCNLinux联盟 。对自己的bss空间进行0初始化 KCNLinux联盟 。为使虚拟内存工作,要保证最少的管理信息。然后是虚拟空间动作。 KCNLinux联盟 也就是,调用cpu有强的依赖关系的过程init386()(@i386/i386/machdep.c), KCNLinux联盟 然后进行kernel内的管理信息初始化,i/o设备的登记,生成4个kernel process KCNLinux联盟 ,再调用main()(@kern/init_main.c)。当main()返回locore.s时,应该有如下 KCNLinux联盟 5个进程: KCNLinux联盟 PID TT STAT TIME COMMAND KCNLinux联盟 0 ?? DLs 0:00.17 (swapper) KCNLinux联盟 1 ?? Is 0:00.19 /sbin/init -- KCNLinux联盟 2 ?? DL 0:56.60 (pagedaemon) KCNLinux联盟 3 ?? DL 0:00.06 (vmdaemon) KCNLinux联盟 4 ?? DL 6:07.65 (updata) KCNLinux联盟 从locore.s返回到process #1,/sbin/init开始动作,然后转向freebsd的普通 KCNLinux联盟 动作。 KCNLinux联盟 init386()和main()的处理大致如下: KCNLinux联盟 。init386() KCNLinux联盟 GDT和LDT,IDT,task stages处理的初始化,例外处理等locore.s没做的 KCNLinux联盟 事情,虚拟内存初始化。然后,根据boot program的参数,增加物理内 KCNLinux联盟 存page数。然后,作成process #0的雏形。 KCNLinux联盟 。main() KCNLinux联盟 逐步调用构成kernel模块的的初始化部分。 KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 FreeBSD核心探讨(翻译)3 KCNLinux联盟 KCNLinux联盟 (续上,liangvy.icewolf.leon翻译) KCNLinux联盟 KCNLinux联盟 但是,kernel构成的各个模块的初始化子程序一个个的列举出来运行很显然是 KCNLinux联盟 不行的。通常是利用时间连表的技能来运行它(ld command)。也就是,程序 KCNLinux联盟 是以很多个source分开编译和联结。相同的模块名字就对应于相同的地址来进 KCNLinux联盟 行调用。它在时间链表里面自动调节执行。 KCNLinux联盟 初始化时候,main()函数要call的模块利用在sys/kernel.h里面定义的宏 KCNLinux联盟 SYSINIT()和SYSINIT_KT()进行登记。这样,kernel在link的时候,ld命令就 KCNLinux联盟 能够得到那些信息和进行配置列表。这个列表就是kernel的组成模块的初始化 KCNLinux联盟 routine的登记。检查source, KCNLinux联盟 就可以找到初始化routine的部分。 KCNLinux联盟 如表: KCNLinux联盟 print_caddr_t(copyright) kern/init_main.c KCNLinux联盟 vm_men_init(NULL) vm/vm_init.c KCNLinux联盟 syctl_order(&sysctl_) kern/kern_sysctl.c KCNLinux联盟 kmemnit(NULL) kern/kern_malloc.c KCNLinux联盟 fpu_init(NULL) i386/i386/math_emulate.c KCNLinux联盟 cpu_startup(NULL) i386/i386/machdep.c KCNLinux联盟 gnufpu_init(NULL) miscfs/devfs/devfs_tree.c KCNLinux联盟 ... KCNLinux联盟 各个device的major号与处理routine的登记 (major循序号) KCNLinux联盟 ... KCNLinux联盟 configure(NULL) i386/i386/autoconf.c KCNLinux联盟 proc0_init(NULL) kern/init_main.c KCNLinux联盟 rqinit(NULL) kern/kern_synch.c KCNLinux联盟 vm_init_limits(&proc0) vm/vm_glue.c KCNLinux联盟 vfsinit(NULL) kern/vfs_init.c KCNLinux联盟 elf_insert_brand_entry(&linux_brand) i386/linux/linux_sysvec.c KCNLinux联盟 initclocks(NULL) kern/kern_clock.c KCNLinux联盟 mbinit(NULL) kern/uipc_mbuf.c KCNLinux联盟 clst_init(NULL) kern/tty_subr.c KCNLinux联盟 shmnit(NULL) kern/sysv_shm.c KCNLinux联盟 seminit(NULL) kern/sysv_sem.c KCNLinux联盟 msginit(NULL) kern/sysc_msg.c KCNLinux联盟 kludge_splimp(&x_save_spl) kern/uipc_domain.c KCNLinux联盟 ifinit(NULL) net/if.c KCNLinux联盟 domaininit(NULL) kern/uipc_domain.c KCNLinux联盟 kludge_splx(&x_save_spl) kern/uipc_domain.c KCNLinux联盟 kmstartup(NULL) kern/subr_prof.c KCNLinux联盟 sched_setup(NULL) kern/init_main.c KCNLinux联盟 xxx_vfs_mountroot(NULL) kern/init_main.c KCNLinux联盟 xxx_vfs_root_fdtab(NULL) kern/init_main.c KCNLinux联盟 swapinit(NULL) kern/init_main.c KCNLinux联盟 proc0_post(NULL) kern/init_main.c KCNLinux联盟 kthread_init(NULL) kern/init_main.c|| KCNLinux联盟 kproc_start(&page_kp) vm/vm_pageout.c|| KCNLinux联盟 kproc_start(&vm_kp) vm/vm_pageout.c|| KCNLinux联盟 kproc_start(&up_kp) kern/vfs_bio.c|| KCNLinux联盟 scheduler(NULL) vm/vm_glue.c KCNLinux联盟 (||表示有多个程序) KCNLinux联盟 proc-post()被呼叫后,main()就是在对应process 0 的kernel的虚拟 KCNLinux联盟 内存里动作。kthread_init(),kproc_start(&page_kp),kproc_start(&vm_kp) KCNLinux联盟 ,kproc_start(&up_kp)等这几个进程,在fork()后相继被调用。它就是相 KCNLinux联盟 应的进程1,2,3,4等。 KCNLinux联盟 除process 1 以外,其他的进程调用并不返回调用的地址。(也就是,main() KCNLinux联盟 的跟随执行后,并不返回locore.s)。对于process #1的kernel的虚拟内存, KCNLinux联盟 在kthread_init()返回后,main()的跟随就完了,回到locore.s后,process #1 KCNLinux联盟 的进程空间的配置文件/sbin/init就被执行。 KCNLinux联盟 main()在process #0对应的kernel虚拟内存运行后,进入时间链表scheduler()。 KCNLinux联盟 这个并不返回。那现在就有五个进程了。 KCNLinux联盟 然后,fork() 的调用在下面说明。 KCNLinux联盟 1,分配process ID,保证struct proc()用的空间。 KCNLinux联盟 2,复制父亲的process的虚拟内存空间,作成物理内存的变换表。对 KCNLinux联盟 应两个进程,采用相对应的物理内存表。 KCNLinux联盟 3,给回父亲的struct proc和struct user,然后对子进程的struct和 KCNLinux联盟 struct user进行初始化。 KCNLinux联盟 4,kernel的stacker也进行复制。 KCNLinux联盟 5,返回父进程后,标记生成的子进程。完成处理。 KCNLinux联盟 但是,process #0 -- 4 这五个进程的虚拟内存里面什么都没有。这些是核心 KCNLinux联盟 进程的特殊部分。进程0,2,3是调节系统存在的进程的执行优先级,监视物理 KCNLinux联盟 内存的不足,如果不够就使用swap区进行交换。进程4的作用就是定期调查核心 KCNLinux联盟 的unix文件系统的管理信息与驱动程序的管理信息的一致性,使它的信息一直 KCNLinux联盟 是最新的。 KCNLinux联盟 KCNLinux联盟 1.3.3 /sbin/init KCNLinux联盟 从kernel里面看,/sbin/init就是单一的进程空间里动作,与一般的 KCNLinux联盟 user program一样,提供user使用的unix文件系统的环境的服务。 KCNLinux联盟 核心启动后最初的动作就是/sbin/init。作用如下: KCNLinux联盟 。确保file system的一致性,进行mount。 KCNLinux联盟 。之后,network的设定和各种daemon的启动。 KCNLinux联盟 。监视终端的login的配置和动作状态。这个动作完了后(logout), KCNLinux联盟 修改和配置 login。 KCNLinux联盟 也就是说,如果没有它,用户就不能使用unix文件系统。还有就是,如果boot KCNLinux联盟 progam参数指定-s的话,它就过渡到单一的用户模式。相对来说,普通的用户 KCNLinux联盟 模式也就是multi模式。为了使普通用户能够使用系统,/sbin/init的参考文件 KCNLinux联盟 主要在/etc目录里放着。主要就是运行/etc/rc文件对系统进行初始化。 KCNLinux联盟 /etc/rc文件的主要内容和作用如下: KCNLinux联盟 。使系统能够使用swap区 KCNLinux联盟 。检查/etc/fstab,检查它的连贯性,如果有问题就转到单一的用户模式 KCNLinux联盟 。mount nfs以外的文件系统 KCNLinux联盟 。读入network 的设定和各种daemon进程的设定情况的记录文件 KCNLinux联盟 /etc/c.conf,这个内容作为shell script的变量设定,以下的就是 KCNLinux联盟 各个shell的动作调整 KCNLinux联盟 。serial的初始化(/etc/rc.serial) KCNLinux联盟 。运行PCMCIA卡的插拔监控守护进程(/etc/rc.pccard) KCNLinux联盟 。network的部分初始化(/etc/rc.network) KCNLinux联盟 。如果有nfs的时候就进行mount操作 KCNLinux联盟 。network的最终初始化(/etc/rc.network:启动和entwork有关的daemon) KCNLinux联盟 。共有库的有关信息的初始化 KCNLinux联盟 。intd,lpd,sendmail的启动 KCNLinux联盟 。依赖系统的一些初始化进程 KCNLinux联盟 /etc/rc的处理完了后,/sbin/init就对/etc/ttys等记述的一些终端的用户login进行 KCNLinux联盟 监视。对于这个,/etc/ttys里指定的终端,fork()后的进程里: KCNLinux联盟 。exec()指定的程序(普通的情况是/usr/libexec/getty) KCNLinux联盟 。/usr/libexec/getty进行终端速度等的设定。提示login:,等待用户输入 KCNLinux联盟 。用户输入后,名字作为参数exec() /etc/bin/login KCNLinux联盟 。/usr/bin/login就提示出passwd:,等待用户的输入 KCNLinux联盟 。准备user名和passwd,对输入的用户名进行确定,正确的话就exec()用户 KCNLinux联盟 shell KCNLinux联盟 KCNLinux联盟 下图就是/sbin/init的监视进程图: KCNLinux联盟 KCNLinux联盟 process #1 KCNLinux联盟 -------------------------------------------------------->; KCNLinux联盟 /sbin/init | ^ \ KCNLinux联盟 | fork() | | fork() KCNLinux联盟 + exec() exec() exec() | | exec() KCNLinux联盟 process #n |---------->;+--------->;+------------------*+-------- KCNLinux联盟 getty login user的login shell process #m KCNLinux联盟 KCNLinux联盟 (第一章完,下一章介绍文件系统和驱动程序,liangvy) KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 FreeBSD核心探讨.4.驱动程序篇 KCNLinux联盟 KCNLinux联盟 翻译:liangvy liangvy@bigfoot.com icewolf.leon :-) KCNLinux联盟 版权所有,可以转贴 KCNLinux联盟 KCNLinux联盟 第二章 文件系统和设备驱动程序 KCNLinux联盟 KCNLinux联盟 这章主要介绍文件系统和特殊的设备文件以及它们的对应关系。 KCNLinux联盟 KCNLinux联盟 2..1 disk上的 unix file system 的基本知识 KCNLinux联盟 首先介绍一下经典的unix file system的思维方法。 KCNLinux联盟 disk 的 partition就是从0到512byte的连续长度的block的东西。这里有 KCNLinux联盟 1.file/directory有关的固定长度的信息,i-node KCNLinux联盟 2.file/directory的本体,data block KCNLinux联盟 的两样不同的东西。partition的前面的附近块(block#16 ,1--15用于boot KCNLinux联盟 program :-))就是i-node,data block用的领域等等的开始位置(block号) KCNLinux联盟 和长度(block数量)等的记录,叫做super-block。一个block可能的容量只 KCNLinux联盟 能有固定数目的i-node,所以如果分配了固定的i-node,收录了节点号和节 KCNLinux联盟 点的块号和块的位置就可以计算出来。 KCNLinux联盟 i-node就是 KCNLinux联盟 。表明i-node的种类(file ,direstory,device等) KCNLinux联盟 。这个节点参考的次数(目录数) KCNLinux联盟 。参考,作成,变化的时间 KCNLinux联盟 。权限 KCNLinux联盟 。所有者的user id / group id KCNLinux联盟 。本体的长度 KCNLinux联盟 。收集本体的data block的block号码的固定长度的对应表 KCNLinux联盟 的一些记录。因为data block的对应表是固定的关系,比 KCNLinux联盟 如10个,最长就能够作出512*10=5k为止的file。 KCNLinux联盟 KCNLinux联盟 当文件比块大的时候,unix就采用成组联结的方式对它们进行管理。就是 KCNLinux联盟 把所有的空闲块以一定数目为一组的方法作成单向空闲块stacker。 KCNLinux联盟 特别地,文件的从先头的byte位置开始和i-node内的对应表有着密切的关系。 KCNLinux联盟 而且,对于i-node的输入输出,可以对应指定位置的数据块进行读写。重要 KCNLinux联盟 的是,核心可以依照这个管理表对io装置进行管理。 KCNLinux联盟 unix对io设备的操作也是作为(特殊)文件进行的。对于用i-node进行 KCNLinux联盟 描述的io设备,data block数据块的对应表就没必要了。这个部分的io设备 KCNLinux联盟 的识别就通过device号码来进行。向这些对i-node进行输入输出处理的, KCNLinux联盟 就又设备驱动号区别,来进行device driver驱动。 KCNLinux联盟 那么,节点怎么的进行查找呢?partition的最初的目录(根目录)就是, KCNLinux联盟 从第二个i-node开始,一个一个顺着节点进行查找。 KCNLinux联盟 比如,对于目录/uuu/vvv/.../yyy/zzz的查找方式,有这种关系: KCNLinux联盟 。i-node #2 所存放的是root directory。读入它的本体,就可以找到 KCNLinux联盟 相应的uuu所对应的i-node。 KCNLinux联盟 。读入这个i-node所存放的directory的i-node本体,找到相应的vvv节点。 KCNLinux联盟 ...... KCNLinux联盟 查找对应yyy的节点 KCNLinux联盟 。读入这个节点的本体信息,这里包含目录本题的内容,这样就可以找到 KCNLinux联盟 zzz所对应的i-node。 KCNLinux联盟 目录里面由于记录了对应文件名的节点号,所以,也有可能同一个节点号 KCNLinux联盟 根据文件名不一样,就可以找到不同的目录名。这就是硬连接(hard link). KCNLinux联盟 但是,节点号有只存在于节点所在的分区的含义,所以,不同的分区, KCNLinux联盟 这种硬连接就不具有存在的可能性。为了解决这个矛盾,就有了符号连接 KCNLinux联盟 (symble link)的说法。当节点是输入符号连接的时候,符号连接就包含 KCNLinux联盟 了这个节点的data block所指定的路径名。但是,空连接和loop连接这种 KCNLinux联盟 情况也是允许的,所以核心要指定循环连接的最大次数。具体由参数 KCNLinux联盟 MAXSYMLINKS(@sys/param.h)指定。 KCNLinux联盟 这样,多个分区建立一个文件系统就有可能了。启动核心的分区作为一个 KCNLinux联盟 已存的文件系统,其他的分区就嫁接到目录层上面。这个操作过程就是mount。 KCNLinux联盟 利用mount指令,就可以实现上面的操作。但是,mount之前的目录,在mount后 KCNLinux联盟 就给屏蔽了,直到mount结束,那些目录就可以再现。 KCNLinux联盟 以上就是经典的unix文件系统理论。但是,对于读入了i-node,就去读 KCNLinux联盟 data block ,这种情况,对于一个比较大的分区,硬盘磁头向disk head的距 KCNLinux联盟 离就太大了。总的来说,访问时间就会变长。在这里有一些指导思想: KCNLinux联盟 。分区要比较小,多分小区 KCNLinux联盟 。了解超级块的地位,超级块记录了分区的信息,考虑由于介质的原因而 KCNLinux联盟 使这个超级块造成损害,所以,在分区内部就必须为它准备多几个拷贝。 KCNLinux联盟 。目录和它下层的文件,要在相同的领域内放置。 KCNLinux联盟 。确保单位data block要比磁盘的block大。 KCNLinux联盟 考虑了一些东西后,经过改良标准,freebsd就采用一个叫做FFS的文件系 KCNLinux联盟 统(Fast File System),但这只是i-node领域/data领域的配置方法的变化,基 KCNLinux联盟 本的考虑方法并没有变。对磁盘分区进行文件系统的构造的初始化由命令newfs KCNLinux联盟 提供。看看它的source就知道怎么配置的了。其他的构造(......)对应于kernel KCNLinux联盟 的source,对于构成boot program的文件disk.c和sys.c(@i386/boot/biosboot) KCNLinux联盟 比较简单易懂(单纯性)。 KCNLinux联盟 上面讲述的i-node对disk的partition的记录形式,详细的(source)在 KCNLinux联盟 struct dinode(@ufs/ufs/dinode.h)里面有。在核心内部使用的,包含这个东西 KCNLinux联盟 的是struct inode(@ufs/ufs.inode.h)。 KCNLinux联盟 KCNLinux联盟 描述io设备的文件叫特殊文件(special file),他对应的i-node有两个种 KCNLinux联盟 类: KCNLinux联盟 。块型(block) KCNLinux联盟 和装置的固有的数据记录的单位(大多数的情况是512byte)无关。读写 KCNLinux联盟 的最小单位是1byte,可以在任意的场所里任意长度的data。核心对各个 KCNLinux联盟 block型的特殊文件进行固定的记录单位长度(倍数)进行缓冲(buffer) KCNLinux联盟 管理,这样就可以处理任意长度的读写了. KCNLinux联盟 。文字型(char) KCNLinux联盟 读写的基本单位是,受到装置固有的date记录单位长的限定。没有block KCNLinux联盟 型的缓冲管理,对应于装置的物理特性,读写属于专用。或者说,是读写 KCNLinux联盟 两用。 KCNLinux联盟 除了网络接口之外,io装置可以全部分为文字型和块型两个大类。总的来说, KCNLinux联盟 磁盘操作的两样都用,但其他的io装置只有文字型。还有就是一些没对应物理设 KCNLinux联盟 备的kernel modules提供的虚拟设备也有,它们对应着文字型的特殊文件。特殊 KCNLinux联盟 文件习惯放在目录/dev里面。 KCNLinux联盟 KCNLinux联盟 对于特殊设备文件的i-node有block和chat两个类,设备通过驱动号进行记录 KCNLinux联盟 。通过这些,就可以识别device driver。device 号就是major号(8bit)(主设备 KCNLinux联盟 号)和minor号(24bit)(辅助设备号),device driver的识别就是由major的不 KCNLinux联盟 一样而区别。而且呢,block型,char型的等等可能存在最大数目是256种类。一般的 KCNLinux联盟 情况,同种类的设备不同数目的区别就是通过辅助设备号进行识别。实际上,对于 KCNLinux联盟 disk的特殊文件,有disk/slide/partition表示法,而且,文字型,块型等的特殊 KCNLinux联盟 设备文件也存在。以下就是一个ide硬盘的的文字型特殊设备文件的例子: KCNLinux联盟 /dev/rwd0 1台ide的硬盘 KCNLinux联盟 /dev/rwd0s1 1台ide的硬盘的slide #1 KCNLinux联盟 /dev/rwd0s2 1台ide的硬盘的slide #2 KCNLinux联盟 /dev/rwd0s2a slide #2的partition a KCNLinux联盟 /dev/rwd0s2b slide #2的partition b KCNLinux联盟 ... KCNLinux联盟 /dev/rwd0s3 1台的ide的硬盘的slide #3 KCNLinux联盟 KCNLinux联盟 如果把rwd换成wd,对应的就是block型的特殊设备文件了。 KCNLinux联盟 对于磁盘,有如下的使用方法: KCNLinux联盟 。对于slide的文字型特殊文件 KCNLinux联盟 读写disk label时候使用(disklabel command) KCNLinux联盟 。对于对应的partition的文字型特殊文件 KCNLinux联盟 在分区上建立unix文件系统时候(newfs command),文件系统修复, KCNLinux联盟 检查(fsck)时候使用 KCNLinux联盟 。对于partition的block型的特殊文件 KCNLinux联盟 作为mount命令的参数使用 KCNLinux联盟 (下一节介绍虚拟文件系统和v-node,要休息了:-) ) KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 FreeBSD核心探讨.5.驱动程序篇 KCNLinux联盟 KCNLinux联盟 2.2 虚拟文件系统和v-node KCNLinux联盟 FreeBSD在disk上的除了ffs以外还可以操作各种各样的文件系统。主要的如 KCNLinux联盟 下: KCNLinux联盟 。cd9660 KCNLinux联盟 可以对ISO9660形式的cd-rom的目录/文件构造的文件系统进行mount, KCNLinux联盟 locate等目录层的操作 KCNLinux联盟 。ms-dos KCNLinux联盟 对ms-dos文件系统进行目录层次的mount,定位等操作 KCNLinux联盟 。mfs KCNLinux联盟 通过使用虚拟内存对swap区的一部分进行unix文件系统的构造,定位 KCNLinux联盟 作为目录的一部分进行读写 KCNLinux联盟 。nfs KCNLinux联盟 由nfs server提供的remote目录级进行mount,定位的目录层操作。 KCNLinux联盟 。null KCNLinux联盟 对已经存在的目录层的使用别名 KCNLinux联盟 。union KCNLinux联盟 对已有的目录A(上层)在下层目录B上进行重叠 (不大理解这的意思 KCNLinux联盟 ,大概是在下层目录里面又嫁接了上层目录的意思:译者)。文件名的查 KCNLinux联盟 找由上层优先进行。没有的话就转道下层。如果对下层的文件进行写操作 KCNLinux联盟 ,它的拷贝就在上层上进行。举例说明,作业目录在上层,但cd-rom的源 KCNLinux联盟 在下层,两个目录重叠,那么编译source的时候,就相当方便了。 KCNLinux联盟 。procfs KCNLinux联盟 对于进程号的目录作成mount point。通过文件名对各个目录的进程进行 KCNLinux联盟 控制。 KCNLinux联盟 。kernfs KCNLinux联盟 为了对动作中的kernel有关的信息进行参考,而作成的mount point KCNLinux联盟 。fdesc KCNLinux联盟 对于各个进程,用它所打开的文件柄对应的文件作成的mount point KCNLinux联盟 KCNLinux联盟 实际上,在核心内部,为了对它们进行统一操作,就对文件系统和v-node KCNLinux联盟 进行抽象化,实际的处理过程就是调用各类的文件系统的模块进行处理。 KCNLinux联盟 KCNLinux联盟 2.2.1对虚拟文件系统的操作 KCNLinux联盟 各个文件系统可以提供的操作的一览如下,它在struct vfsops KCNLinux联盟 (@sys/mount.h)里面定义: KCNLinux联盟 。对文件系统进行mount的操作 KCNLinux联盟 。本文件系统的开始动作的操作 KCNLinux联盟 。本文件系统的umount操作 KCNLinux联盟 。表达文件系统的根的v-node的查找操作 KCNLinux联盟 。对一般用户的权限控制 KCNLinux联盟 。取得文件系统的状态 KCNLinux联盟 。内存内的管理信息写入介质中 KCNLinux联盟 。从i-node到v-node的取得操作 KCNLinux联盟 。v-node和nfs的文件柄的相互变换的操作 KCNLinux联盟 。文件系统实际的模块的初始化 KCNLinux联盟 KCNLinux联盟 对于文件系统,各个实际的操作routine在vfsops的形式提供准备工作。各个文件系 KCNLinux联盟 统的vfsops,在以下的表里的source进行定义: KCNLinux联盟 KCNLinux联盟 -------------------------------------------------------------- KCNLinux联盟 file system vfsops的定义 source KCNLinux联盟 -------------------------------------------------------------- KCNLinux联盟 ufs ufs_vfsops ufs/ffs/ffs_vfsops.c KCNLinux联盟 cd9660 cd9660_vfsops isofs/cd9660/cd9660_vfsops.c KCNLinux联盟 msdos msdosfs_vfsops msdosfs/msdosfs_vfsops.c KCNLinux联盟 mfs mfs_vfsops ufs/mfs/mfs_vfops.c KCNLinux联盟 nfs nfs_vfsops nfs/nfs_vfsops.c KCNLinux联盟 null null_vfsops miscfs/nullfs/null_vfsops.c KCNLinux联盟 nuion union_vfsops miscfs/union/union_vfsops.c KCNLinux联盟 procfs procfs_vfsops miscfs/procfs/procfs_vfsops.c KCNLinux联盟 kernfs kernfs_vfsops miscfs/kernfs/kernfs_vfsops.c KCNLinux联盟 fdesc fdesc_vfsops miscfs/fdesc/fdesc_vfsops.c KCNLinux联盟 devfs devfs_vfsops miscfs/devfs/devfs_vfsops.c KCNLinux联盟 ext2fs ext2fs_vfsops gnu/ext2fs/ext2_vfsops.c KCNLinux联盟 lfs lfs_vfsops ufs/lfs/lfs_vfsops.c KCNLinux联盟 portal portal_vfsops miscfs/portal.portal_vfsops.c KCNLinux联盟 umap umap_vfsops miscfs/umapfs/umap_vfsops.c KCNLinux联盟 --------------------------------------------------------------- KCNLinux联盟 这些就是文件系统的实际模块(*_vfsops.c),文件系统名称,文件系统号等等 KCNLinux联盟 在struct vfsconf(@sys/mount.h)里面汇总,各个模块里用宏VFS_SET()进入核 KCNLinux联盟 心。 KCNLinux联盟 根据main()(@kern/init_main.c),在kernel初始化的过程中,vfsinit() KCNLinux联盟 (@kern/vfs_init.c)里面有 KCNLinux联盟 struct vfsconf *vfsconf[MOUNT_MAXTYPE+1]; KCNLinux联盟 struct vfsops *vfssw[MOUNT_MAXTYPE+1]; KCNLinux联盟 各种东西的设定,这些是,管理mount信息的struct mount(@sys/mount.h)的成员 KCNLinux联盟 mnt_vfc和mnt_op要指定所对应的文件系统的vfsconf,vfssw。还有宏VFS_操作名 KCNLinux联盟 (struct mount *,..)里,可以各个操作的调用。 KCNLinux联盟 KCNLinux联盟 2.2.2对v-node的操作 KCNLinux联盟 虚拟文件系统就是通过对i-node的抽象化之后的v-node的文件/目录进行io处理。 KCNLinux联盟 为了这个目的,作为对v-node的适用处理,有 KCNLinux联盟 。从v-node到文件名的查找,返回v-node KCNLinux联盟 。打开/关闭v-node KCNLinux联盟 。检查是否可能访问v-node KCNLinux联盟 。得到-v-node的属性 KCNLinux联盟 。设定v-node的属性 KCNLinux联盟 。对v-node的输入/输出 KCNLinux联盟 。扩展v-node的硬连接和符号连接 KCNLinux联盟 。对v-node进行目录的作成和删除 KCNLinux联盟 。。。。 KCNLinux联盟 由这里开始,一共定义了41个。 KCNLinux联盟 v-node由struct vnode(@sys/vnode.h)里定义,作为类别在enum vtype KCNLinux联盟 里面表示出来,一共是9种类。它包含着在各个文件系统上对各个的文件/目录(包 KCNLinux联盟 括特殊)文件进行统一识别的信息。为了实现这样,v-node一连串的操作就是在各 KCNLinux联盟 模块里通过宏VNODEOP_SET()和核心通讯。这些操作名和实现的routine只需要必要 KCNLinux联盟 的几个对应。在核心初始化里,vfs_opv_init()(@kern/vfs_init.c)就使从数据得 KCNLinux联盟 到的号码一一对应,收集了routine的地址的同一size的配列再进行组合。各个 KCNLinux联盟 v-node就一个一个指向这些配列。对v-node的操作在vnode_if.h里定义: KCNLinux联盟 它以 KCNLinux联盟 VOP_操作名(v-node,...) KCNLinux联盟 的统一形式记述。 KCNLinux联盟 KCNLinux联盟 下面是对v-node的操作的定义source: KCNLinux联盟 ------------------------------------------------------------------------ KCNLinux联盟 各个v-node操作(vnodeopv) source KCNLinux联盟 ------------------------------------------------------------------------ KCNLinux联盟 cd9660_fifoop_opv_desc isofs/cd9660/cd9660_vnops.c KCNLinux联盟 cd9660_specop_opv_desc isofs/cd9660/cd9660_vnops.c KCNLinux联盟 cd9660_vnodeop_opv_desc isofs/cd9660/cd9660_vnops.c KCNLinux联盟 dead_vnodop_opv_desc miscfs/deadfs/dead_devfs_vnops.c KCNLinux联盟 devfs_vnodeop_desc miscfs/devfs/devfs_vnops.c KCNLinux联盟 ext2fs_fifoop_opv_desc gnu/ext2fs/ext2fs_vnops.c KCNLinux联盟 ext2fs_specop_opv_desc gnu/ext2fs/ext2fs_vnops.c KCNLinux联盟 ext2fs_vnodeop_opv_desc gnu/ext2fs/ext2fs_vnops.c KCNLinux联盟 fdesc_vnodeop_opv_desc miscfs/fdesc/fdesc_vnops.c KCNLinux联盟 ffs_fifoop_opv_desc ufs/ffs/ffs_vnops.c KCNLinux联盟 ffs_specop_opv_desc ufs/ffs/ffs_vnops.c KCNLinux联盟 ffs_vnodeop_opv_desc ufs/ffs/ffs_vnops.c KCNLinux联盟 fifo_nfsv2nodeop_opv_desc nfs/nfs_vnops.c KCNLinux联盟 fifo_vnodeop_opv_desc miscfs/fifofs/fifo_vnops.c KCNLinux联盟 kernfs_vnodeop_opv_desc miscfs/kernfs/kernfs_vnops.c KCNLinux联盟 lfs_fifoop_opv_desc ufs/lfs/lfs_vnops.c KCNLinux联盟 lfs_specop_opv_desc ufs/lfs/lfs_vnops.c KCNLinux联盟 lfs_vnodeop_opv_desc ufs/lfs/lfs_vnops.c KCNLinux联盟 mfs_vnodeop_opv_desc ufs/mfs/mfs_vnops.c KCNLinux联盟 msdosfs_vnodeop_opv_desc msdosfs/msdosfs_vnops.c KCNLinux联盟 nfsv2_vnodeop_opv_desc nfs/nfs_vnops.c KCNLinux联盟 null_vnodeop_opv_desc miscfs/nullfs/null_vnops.c KCNLinux联盟 portal_vnodeop_opv_desc miscfs/portal/portal_vnops.c KCNLinux联盟 procfs_vnodeop_opv_desc miscfs/procfs/procfs_vnops.c KCNLinux联盟 spec_nfsv2nodeop_opv_desc nfs/nfs_vnops.c KCNLinux联盟 spec_vnodeop_opv_desc miscfs/specfs/spec_vnops.c KCNLinux联盟 umap_vnodeop_opv_desc miscfs/umapfs/umap_vnops.c KCNLinux联盟 union_vnodeop_opv_desc miscfs/union/union_vnops.c KCNLinux联盟 ------------------------------------------------------------------------ KCNLinux联盟 这个基础上,spec_vnodeop_opv_spec里描述的操作群就是device driver KCNLinux联盟 interface的东西!! KCNLinux联盟 KCNLinux联盟 ( 本小节完,待本岛主有空再继续:-) ) KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 KCNLinux联盟 FreeBSD核心探讨.6.驱动程序篇 | |