启动信息与RCd.docx
《启动信息与RCd.docx》由会员分享,可在线阅读,更多相关《启动信息与RCd.docx(47页珍藏版)》请在冰豆网上搜索。
启动信息与RCd
Linux启动信息解析
组名:
CloudWalker
组长:
郑祥云
组员:
郑祥云,徐绩,王新华
日期:
2010-7-24
目录
Linux启动信息解析1
目录2
1.项目需求分析3
1.1项目背景:
3
1.2时间:
3
1.3项目要求分析:
3
2.Linux启动过程4
2.1Linux下各个目录的作用4
2.2Linux启动过程4
2.2.1Linux的引导过程5
2.2.2运行级别(runlevel)5
2.2.3/etc/rc.d/与/etc/rc.d/init.d的关系5
3./init/main.c中init()函数7
4.启动信息10
1.项目需求分析
1.1项目背景:
在学习操作系统中,操作系统的如何启动是一个难点,本文基于Linux开源操作系统,分析了从BIOS加载BOOTLOAD,操作系统接管CPU后,init()函数所做的事情以及如何初始化系统的各种服务以及SHELL。
1.2时间:
开始时间:
2010-7-25结束时间:
2010-7-25
1.3项目要求分析:
1)介绍Linux启动所需的目录。
2)Linux启动过程。
3)/etc/rc.d/与/etc/rc.d/init.d的关系。
4)分析init/main.c代码中init()函数。
2.Linux启动过程
2.1Linux启动所需的目录
init.d/:
各种服务器和程序的二进制文件存放目录。
rcx.d/:
各个启动级别的执行程序连接目录。
里头的东西都是指向init.d/的一些软连接。
还有三个脚本:
rc.sysinit,rc,rc.local。
/etc/rc.d/init.d/目录下的脚本就类似与windows中的注册表,在系统启动的时候某些指定脚本将被执行。
在Redhat中,/etc/rc.d/rc.sysinit主要做在各个运行模式中相同的初始化工作,包括:
i.调入keymap以及系统字体
ii.启动swapping
iii.设置主机名
iv.设置NIS域名
v.检查(fsck)并mount文件系统
vi.打开quota
vii.装载声卡模块
viii.设置系统时钟
ix.等等。
2.2Linux启动过程
redhat的启动方式和执行次序是:
i.加载内核
ii.执行init程序
iii./etc/rc.d/rc.sysinit#由init执行的第一个脚本
iv./etc/rc.d/rc$RUNLEVEL#$RUNLEVEL为缺省的运行模式
v./etc/rc.d/rc.local
vi./sbin/mingetty#等待用户登录
init在等待/etc/rc.d/rc执行完毕之后(因为在/etc/inittab中/etc/rc.d/rc的action是wait),将在指定的各个虚拟终端上运行/sbin/mingetty,等待用户的登录。
至此,Linux的启动结束。
2.2.1Linux的引导过程
系统启动之后,在进入init.d之前,我们先来看看系统都做了什么工作.
我们从比较高的角度去看开始引导的整个过程,比较清晰明了。
系统加电之后,首先进行的硬件自检,然后是bootloader对系统的初始化,加载内核。
内核被加载到内存中之后,就开始执行了。
一旦内核启动运行,对硬件的检测就会决定需要对哪些设备驱动程序进行初始化。
从这里开始,内核就能够挂装根文件系统(这个过程类似于Windows识别并存取C盘的过程)。
内核挂装了根文件系统,并已初始化所有的设备驱动程序和数据结构等之后,就通过启动一个叫init的用户级程序,完成引导进程。
2.2.2运行级别(runlevel)
init进程是系统启动之后的第一个用户进程,所以它的pid(进程编号)始终为1。
init进程上来首先做的事是去读取/etc/目录下inittab文件中initdefaultid值,这个值称为运行级别(run-level)。
它决定了系统启动之后运行于什么级别。
运行级别决定了系统启动的绝大部分行为和目的。
这个级别从0到6,具有不同的功能。
不同的运行级定义如下:
#0-停机(千万别把initdefault设置为0,否则系统永远无法启动)
#1-单用户模式
#2-多用户,没有NFS
#3-完全多用户模式(标准的运行级)
#4–系统保留的
#5-X11(xwindow)
#6-重新启动(千万不要把initdefault设置为6,否则将一直在重启)
2.2.3/etc/rc.d/与/etc/rc.d/init.d的关系
写到这里,应该差不多要进入init.d了,可是我觉得单写/etc/rc.d/init.d的话不一定能说得清楚明白,就拿它跟/etc/rc.d这个它上一级的目录一起来讨论,可能比较合适一些,因为他们之间有着千丝万缕的关系。
在这里先解释一下init.d里面放的都是什么东西。
这个目录存放的是一些脚本,一般是linux以rpm包安装时设定的一些服务的启动脚本。
系统在安装时装了好多rpm包,这里面就有很多对应的脚本。
执行这些脚本可以用来启动,停止,重启这些服务。
前面说到,/etc/rc.d/init.d这个目录下的脚本就类似与windows中的注册表,在系统启动的时候执行。
程序运行到这里(init进程读取了运行级别),相信从命名的角度大家也能猜到该运行/etc/rc.d/init.d里面的脚本了,不然它为什么也叫init(.d)呢是吧。
没错,是该运行init.d里的脚本了,但是并不是直接运行,而是有选择的因为系统并不需要启动所有的服务。
那么,系统是如何选择哪些需要启动哪些不要呢?
这时刚才说的运行级别就起作用了。
在决定了系统启动的runlevel之后,/etc/rc.d/rc这个脚本先执行。
在RH9和FC7的源码中它都是一上来就check_runlevel()(虽然实现的代码不一样,也大同小异),知道了运行级别之后,对于每一个运行级别,在rc.d下都有一个子目录分别是rc0.d,rc1.d…..rc6.d。
每个目录下都是到init.d目录的一部分脚本一些链接。
每个级别要执行哪些服务就在相对应的目录下,比如级别5要启动的服务就都放在rc5.d下,但是放在这个rc5.d下的都是一些链接文件,链接到init.d中相对应的文件,真正运行的是init.d里的脚本。
到这里,估计大家可能都比较清楚了,我开始也以为是这样的。
可是后来我仔细看过和比较这些链接文件和init.d里真正被执行的脚本的文件名之后,一直有几个问题没弄明白。
借着写这个文章的机会,我做了一些功课,总算是大概解开了那些疑惑。
1、这些链接文件前面为什么会带一个Kxx或者Sxx呢?
是这样的,带K的表示停止(Kill)一个服务,S表示开启(Start)的意思,凡是以Kxx开头的,都以stop为参数来调用;凡是以Sxx开头的,都以start为参数来调用。
调用的顺序按xx从小到大来执行。
例如,假设缺省的运行模式是3,/etc/rc.d/rc就会按上述方式调用/etc/rc.d/rc3.d/下的脚本。
2、K和S后面带的数字呢?
干什么用的
这个我开始的时候还以为是排列起来好看或者数数用呢。
后来发现不是的。
它的作用是用来排序,就是决定这些脚本执行的顺序,数值小的先执行,数值大的后执行。
很多时候这些执行顺序是很重要的,比如要启动Apache服务,就必须先配置网络接口,不然一个没有IP的机子来启动http服务那岂不是很搞笑。
。
。
3、无意中我发现同一个服务带S的和带K的链接到init.d之后是同一个脚本。
我就纳闷了,为什么会是执行同一个脚本呢?
这个时候真是S和K的妙用了,原来S和K并不止是用来看起来分的清楚而已。
S给和K还分别给init.d下面的脚本传递了start和stop的参数。
哦,是这样的(焕然大悟的样子,呵呵)!
这时我才想起来原来曾经无数用过的/etc/rc.d/init.d/networkrestart命令。
原来传S时相当于执行了/etc/rc.d/init.d/xxxstart这条命令,当然K就相当于/etc/rc.d/init.d/xxxstop了.
3./init/main.c中init()函数
init()函数的功能可分为4个部分:
①安装根文件系统;②显示系统信息;②运行系统初始资源配置文件rc中的命令;④执行用户登录shell程序。
代码首先调用系统调用setup(),用来收集硬盘设备分区表信息并安装根文件系统。
在安装根文件系统之前,系统会先判断是否需要先建立虚拟盘.若编译内核时设置了虚拟盘的人小,并在前面内核初始化过程中已经开辟了一块内存用作虛拟盘,则内核就会首先尝试把根文件系统加载到内存的虚拟盘区中.
然后init()打开一个终端设备tty0,并复制其文件描述符以产生标准输入stdin、标准输出stdout和错误输出stderr设备。
内核随后利用这些描述符在终端上显示一些系统信息,例如高速缓冲区中缓冲块总数、主内存区空闲内存总字节数等。
接着init()又新建了一个进程(进程2),并在其中为建立用户交互使用环境而执行一些初始配置操作,即在用户可以使用shell命令行环境之前,内核调用/bin/sh程序运行了配置文件/etc/rc中设置的命令。
rc文件的作用与DOS系统根目录上的AUTOEXEC.BAT文件类似。
这段代码首先通过关闭文件描述符0,并立刻打开文件/etc/rc,从而把标准输入stdin定向到/etc/rc文件上。
这样,所有的标准输入数据都将从该文件中读取。
然后内核以非交互形式执行/bin/sh,从而实现执行/etc/rc文件中的命令。
当该文件中的命令执行完毕后,/bin/sh就会立刻退出。
因此进程2也就随之结束。
init()函数的最后一部份用于在新建进程中为用户建立一个新的会话,并运行用户登录shell程序/bin.sh.在系统执行进程2中的程序时,父进程(init进程)一直等待着它的结束。
随着进程2的退出,父进程就进入到一个无限循环中。
在该循环中,父进程会再次生成一个新进程,然后在该进程中创建一个新的会话。
并以登录shell方式再次执行程序/bin/sh,以创建用户交互shell环境。
然后父进程继续等待该于进程。
登录shell虽然与前而的非交互式shell是同一个程序/bin/sh,但是所使用的命令行参数(argv[])不同。
登录shell的第0个命令行参数的第1个字符一定是一个减号'-'。
这个特定的标志会在/bin/sh执行时通知它这不是一次普通的运行,而是作为登录shell运行/bin/sh的。
从这时开始,用户就可以正常使用Linux命令行环境了,而父进程随之又进入等待状态.此后若用户在命令行上执行了exit或logout命令,那么在显示一条当前登录shell退出的信息后,系统就会在这个无限循环中再次重复以上创建登录shell进程的过程。
以下是init/main.c中的关于init()函数的源代码:
voidinit(void)
{
intpid,i;
setup((void*)&drive_info);
sprintf(term,"TERM=con%dx%d",ORIG_VIDEO_COLS,ORIG_VIDEO_LINES);
(void)open("/dev/tty1",O_RDWR,0);
(void)dup(0);
(void)dup(0);
execve("/etc/init",argv_init,envp_init);
execve("/bin/init",argv_init,envp_init);
execve("/sbin/init",argv_init,envp_init);
/*ifthisfails,fallthroughtooriginalstuff*/
if(!
(pid=fork())){
close(0);
if(open("/etc/rc",O_RDONLY,0))
_exit
(1);
execve("/bin/sh",argv_rc,envp_rc);
_exit
(2);
}
if(pid>0)
while(pid!
=wait(&i))
/*nothing*/;
while
(1){
if((pid=fork())<0){
printf("Forkfailedininit\n\r");
continue;
}
if(!
pid){
close(0);close
(1);close
(2);
setsid();
(void)open("/dev/tty1",O_RDWR,0);
(void)dup(0);
(void)dup(0);
_exit(execve("/bin/sh",argv,envp));
}
while
(1)
if(pid==wait(&i))
break;
printf("\n\rchild%ddiedwithcode%04x\n\r",pid,i);
sync();
}
_exit(0);
}
4.启动信息
[0.000000]Initializingcgroupsubsyscpuset
[0.000000]Initializingcgroupsubsyscpu
[0.000000]Linuxversion2.6.32-22-generic(buildd@palmer)(gccversion4.4.3(Ubuntu4.4.3-4ubuntu5))#36-UbuntuSMPThuJun322:
02:
19UTC2010(Ubuntu2.6.32-22.36-generic2.6.32.11+drm33.2)
[0.000000]KERNELsupportedcpus:
[0.000000]IntelGenuineIntel
[0.000000]AMDAuthenticAMD
[0.000000]NSCGeodebyNSC
[0.000000]CyrixCyrixInstead
[0.000000]CentaurCentaurHauls
[0.000000]TransmetaGenuineTMx86
[0.000000]TransmetaTransmetaCPU
[0.000000]UMCUMCUMCUMC
[0.000000]BIOS-providedphysicalRAMmap:
[0.000000]BIOS-e820:
0000000000000000-000000000009f800(usable)
[0.000000]BIOS-e820:
000000000009f800-00000000000a0000(reserved)
[0.000000]BIOS-e820:
00000000000ca000-00000000000cc000(reserved)
[0.000000]BIOS-e820:
00000000000dc000-00000000000e4000(reserved)
[0.000000]BIOS-e820:
00000000000e8000-0000000000100000(reserved)
[0.000000]BIOS-e820:
0000000000100000-000000003fef0000(usable)
[0.000000]BIOS-e820:
000000003fef0000-000000003feff000(ACPIdata)
[0.000000]BIOS-e820:
000000003feff000-000000003ff00000(ACPINVS)
[0.000000]BIOS-e820:
000000003ff00000-0000000040000000(usable)
[0.000000]BIOS-e820:
00000000e0000000-00000000f0000000(reserved)
[0.000000]BIOS-e820:
00000000fec00000-00000000fec10000(reserved)
[0.000000]BIOS-e820:
00000000fee00000-00000000fee01000(reserved)
[0.000000]BIOS-e820:
00000000fffe0000-0000000100000000(reserved)
[0.000000]DMIpresent.
[0.000000]PhoenixBIOSdetected:
BIOSmaycorruptlowRAM,workingaroundit.
[0.000000]e820updaterange:
0000000000000000-0000000000010000(usable)==>(reserved)
[0.000000]last_pfn=0x40000max_arch_pfn=0x100000
[0.000000]MTRRdefaulttype:
uncachable
[0.000000]MTRRfixedrangesenabled:
[0.000000]00000-9FFFFwrite-back
[0.000000]A0000-BFFFFuncachable
[0.000000]C0000-CBFFFwrite-protect
[0.000000]CC000-EFFFFuncachable
[0.000000]F0000-FFFFFwrite-protect
[0.000000]MTRRvariablerangesenabled:
[0.000000]0base0000000000mask00C0000000write-back
[0.000000]1disabled
[0.000000]2disabled
[0.000000]3disabled
[0.000000]4disabled
[0.000000]5disabled
[0.000000]6disabled
[0.000000]7disabled
[0.000000]PATnotsupportedbyCPU.
[0.000000]------------[cuthere]------------
[0.000000]WARNING:
at/build/buildd/linux-2.6.32/arch/x86/kernel/cpu/mtrr/generic.c:
467generic_get_mtrr+0xeb/0x100()
[0.000000]Hardwarename:
VMwareVirtualPlatform
[0.000000]mtrr:
yourBIOShassetupanincorrectmask,fixingitup.
[0.000000]Moduleslinkedin:
[0.000000]Pid:
0,comm:
swapperNottainted2.6.32-22-generic#36-Ubuntu
[0.000000]CallTrace:
[0.000000][]warn_slowpath_common+0x72/0xa0
[0.000000][]?
generic_get_mtrr+0xeb/0x100
[0.000000][]?
generic_get_mtrr+0xeb/0x100
[0.000000][]warn_slowpath_fmt+0x2b/0x30
[0.000000][]generic_get_mtrr+0xeb/0x100
[0.000000][]mtrr_trim_uncached_memory+0x76/0x32e
[0.000000][]?
native_write_cr4+0x8/0x10
[0.000000][]?
get_mtrr_state+0x102/0x10a
[0.000000][]?
mtrr_bp_init+0x253/0x271
[0.000000][]setup_arch+0x41e/0x69f
[0.000000][]?
printk+0x1d/0x23
[0.000000][]?
default_spin_lock_flags+0x9/0x10
[0.000000][]start_kernel+0xc3/0x357
[0.000000][]i386_start_kernel+0xaa/0xb1
[0.000000]---[endtracea7919e7f17c0a725]---
[0.000000]Scanning0areasforlowmemorycorruption
[0.000000]modifiedphysicalRAMmap:
[0.000000]modified:
0000000000000000-0000000000010000(reserved)
[0.000000]modified:
0000000000010000-000000000009f800(usable)
[0.000000]modified:
000000000009f800-00000000000a0000(reserved)
[0.000000]modified:
00000000000ca000-00000000000cc000(reserved)
[0.000000]modified:
00000000000dc000-00000000000e4000(reserved)
[0.000000]modified:
00000000000e8000-0000000000100000(reserved)
[0.000000]modified:
0000000000100000-000000003fef0000(usable)
[0.000000]modified:
000000003fef00