发信人: 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]
  | 
 
 
 |