精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>电脑技术>>● FreeBSD>>FreeBSD 核心探讨 (cool!)>>FreeBSD核心探讨(翻译)3

主题:FreeBSD核心探讨(翻译)3
发信人: liangvy()
整理人: hahalee(1999-03-17 20:30:07), 站内信件
(续上,liangvy.icewolf.leon翻译)

但是,kernel构成的各个模块的初始化子程序一个个的列举出来运行很显然是
不行的。通常是利用时间连表的技能来运行它(ld command)。也就是,程序
是以很多个source分开编译和联结。相同的模块名字就对应于相同的地址来进
行调用。它在时间链表里面自动调节执行。
初始化时候,main()函数要call的模块利用在sys/kernel.h里面定义的宏
SYSINIT()和SYSINIT_KT()进行登记。这样,kernel在link的时候,ld命令就
能够得到那些信息和进行配置列表。这个列表就是kernel的组成模块的初始化
routine的登记。检查source,
就可以找到初始化routine的部分。
        如表:
        print_caddr_t(copyright)                kern/init_main.c
        vm_men_init(NULL)                       vm/vm_init.c
        syctl_order(&sysctl_)                   kern/kern_sysctl.c
        kmemnit(NULL)                           kern/kern_malloc.c
        fpu_init(NULL)                          i386/i386/math_emulate.c
        cpu_startup(NULL)                       i386/i386/machdep.c
        gnufpu_init(NULL)                       miscfs/devfs/devfs_tree.c
        ...
        各个device的major号与处理routine的登记  (major循序号)
        ...
        configure(NULL)                         i386/i386/autoconf.c
        proc0_init(NULL)                        kern/init_main.c
        rqinit(NULL)                            kern/kern_synch.c
        vm_init_limits(&proc0)                  vm/vm_glue.c
        vfsinit(NULL)                           kern/vfs_init.c
        elf_insert_brand_entry(&linux_brand)    i386/linux/linux_sysvec.c
        initclocks(NULL)                        kern/kern_clock.c
        mbinit(NULL)                            kern/uipc_mbuf.c
        clst_init(NULL)                         kern/tty_subr.c
        shmnit(NULL)                            kern/sysv_shm.c
        seminit(NULL)                           kern/sysv_sem.c
        msginit(NULL)                           kern/sysc_msg.c
        kludge_splimp(&x_save_spl)              kern/uipc_domain.c
        ifinit(NULL)                            net/if.c
        domaininit(NULL)                        kern/uipc_domain.c
        kludge_splx(&x_save_spl)                kern/uipc_domain.c
        kmstartup(NULL)                         kern/subr_prof.c
        sched_setup(NULL)                       kern/init_main.c
        xxx_vfs_mountroot(NULL)                 kern/init_main.c
        xxx_vfs_root_fdtab(NULL)                kern/init_main.c
        swapinit(NULL)                          kern/init_main.c
        proc0_post(NULL)                        kern/init_main.c
        kthread_init(NULL)                      kern/init_main.c||
        kproc_start(&page_kp)                   vm/vm_pageout.c||
        kproc_start(&vm_kp)                     vm/vm_pageout.c||
        kproc_start(&up_kp)                     kern/vfs_bio.c||
        scheduler(NULL)                         vm/vm_glue.c
(||表示有多个程序)
proc-post()被呼叫后,main()就是在对应process 0 的kernel的虚拟
内存里动作。kthread_init(),kproc_start(&page_kp),kproc_start(&vm_kp)
,kproc_start(&up_kp)等这几个进程,在fork()后相继被调用。它就是相
应的进程1,2,3,4等。
除process 1 以外,其他的进程调用并不返回调用的地址。(也就是,main()
的跟随执行后,并不返回locore.s)。对于process #1的kernel的虚拟内存,
在kthread_init()返回后,main()的跟随就完了,回到locore.s后,process #1
的进程空间的配置文件/sbin/init就被执行。
main()在process #0对应的kernel虚拟内存运行后,进入时间链表scheduler()。
这个并不返回。那现在就有五个进程了。
然后,fork() 的调用在下面说明。
        1,分配process ID,保证struct proc()用的空间。
        2,复制父亲的process的虚拟内存空间,作成物理内存的变换表。对
           应两个进程,采用相对应的物理内存表。
        3,给回父亲的struct proc和struct user,然后对子进程的struct和
           struct user进行初始化。
        4,kernel的stacker也进行复制。
        5,返回父进程后,标记生成的子进程。完成处理。
但是,process #0 -- 4 这五个进程的虚拟内存里面什么都没有。这些是核心
进程的特殊部分。进程0,2,3是调节系统存在的进程的执行优先级,监视物理
内存的不足,如果不够就使用swap区进行交换。进程4的作用就是定期调查核心
的unix文件系统的管理信息与驱动程序的管理信息的一致性,使它的信息一直
是最新的。

1。3。3 /sbin/init
从kernel里面看,/sbin/init就是单一的进程空间里动作,与一般的
user program一样,提供user使用的unix文件系统的环境的服务。
核心启动后最初的动作就是/sbin/init。作用如下:
        。确保file system的一致性,进行mount。
        。之后,network的设定和各种daemon的启动。
        。监视终端的login的配置和动作状态。这个动作完了后(logout),
          修改和配置 login。
也就是说,如果没有它,用户就不能使用unix文件系统。还有就是,如果boot 
progam参数指定-s的话,它就过渡到单一的用户模式。相对来说,普通的用户
模式也就是multi模式。为了使普通用户能够使用系统,/sbin/init的参考文件
主要在/etc目录里放着。主要就是运行/etc/rc文件对系统进行初始化。
/etc/rc文件的主要内容和作用如下:
        。使系统能够使用swap区
        。检查/etc/fstab,检查它的连贯性,如果有问题就转到单一的用户模式
        。mount nfs以外的文件系统
        。读入network 的设定和各种daemon进程的设定情况的记录文件
          /etc/c.conf,这个内容作为shell script的变量设定,以下的就是
          各个shell的动作调整
        。serial的初始化(/etc/rc.serial)
        。运行PCMCIA卡的插拔监控守护进程(/etc/rc.pccard)
        。network的部分初始化(/etc/rc.network)
        。如果有nfs的时候就进行mount操作
        。network的最终初始化(/etc/rc.network:启动和entwork有关的daemon)
        。共有库的有关信息的初始化
        。intd,lpd,sendmail的启动
        。依赖系统的一些初始化进程
/etc/rc的处理完了后,/sbin/init就对/etc/ttys等记述的一些终端的用户login进行
监视。对于这个,/etc/ttys里指定的终端,fork()后的进程里:
        。exec()指定的程序(普通的情况是/usr/libexec/getty)
        。/usr/libexec/getty进行终端速度等的设定。提示login:,等待用户输入
        。用户输入后,名字作为参数exec() /etc/bin/login
        。/usr/bin/login就提示出passwd:,等待用户的输入
        。准备user名和passwd,对输入的用户名进行确定,正确的话就exec()用户
          shell
                
下图就是/sbin/init的监视进程图:

process #1
          -------------------------------------------------------->
/sbin/init |                                         ^       \
           | fork()                                  |        | fork()
           + exec()  exec()     exec()               |        | exec()
process #n |---------->+--------->+------------------*+--------
              getty   login      user的login shell       process #m

(第一章完,下一章介绍文件系统和驱动程序,liangvy)

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

[关闭][返回]