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