1、启动信息与RCdLinux启动信息解析组名: Cloud Walker 组长: 郑祥云 组员: 郑祥云,徐绩,王新华 日期: 2010-7-24 目录Linux启动信息解析 1目录 21.项目需求分析 31.1项目背景: 31.2时间: 31.3项目要求分析: 32Linux启动过程 42.1 Linux下各个目录的作用 42.2 Linux启动过程 42.2.1 Linux的引导过程 52.2.2 运行级别(run level) 52.2.3 /etc/rc.d/与/etc/rc.d/init.d的关系 53. /init/main.c中init()函数 74. 启动信息 101.项目需求分
2、析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()函数。2Linux启动过程2.1 Linux启动所需的目录init.d/ :各种服务器和程序的
3、二进制文件存放目录。rcx.d/: 各个启动级别的执行程序连接目录。里头的东西都是指向init.d/的一些软连接。还有三个脚本:rc.sysinit, rc, rc.local。/etc/rc.d/init.d/目录下的脚本就类似与windows 中的注册表,在系统启动的时候某些指定脚本将被执行。在Redhat中,/etc/rc.d/rc.sysinit主要做在各个运行模式中相同的初始化工作,包括:i. 调入keymap以及系统字体ii. 启动swappingiii. 设置主机名iv. 设置NIS域名v. 检查(fsck)并mount文件系统vi. 打开quotavii. 装载声卡模块viii
4、. 设置系统时钟ix. 等等。2.2 Linux启动过程redhat的启动方式和执行次序是:i. 加载内核ii. 执行init程序iii. /etc/rc.d/rc.sysinit # 由init执行的第一个脚本iv. /etc/rc.d/rc $RUNLEVEL # $RUNLEVEL为缺省的运行模式v. /etc/rc.d/rc.localvi. /sbin/mingetty # 等待用户登录init在等待/etc/rc.d/rc执行完毕之后(因为在/etc/inittab中/etc/rc.d/rc的action是wait),将在指定的各个虚拟终端上运行/sbin/mingetty,等待用
5、户的登录。至此,Linux的启动结束。 2.2.1 Linux的引导过程 系统启动之后,在进入 init.d之前,我们先来看看系统都做了什么工作.我们从比较高的角度去看开始引导的整个过程,比较清晰明了。系统加电之后,首先进行的硬件自检,然后是bootloader对系统的初始化,加载内核。内核被加载到内存中之后,就开始执行了。一旦内核启动运行,对硬件的检测就会决定需要对哪些设备驱动程序进行初始化。从这里开始,内核就能够挂装根文件系统(这个过程类似于Windows识别并存取C盘的过程)。内核挂装了根文件系统,并已初始化所有的设备驱动程序和数据结构等之后,就通过启动一个叫 init的用户级程序,完成
6、引导进程。2.2.2 运行级别(run level)init进程是系统启动之后的第一个用户进程,所以它的pid(进程编号)始终为1。init进程上来首先做的事是去读取/etc/目录下inittab 文件中initdefault id值,这个值称为运行级别(run-level)。它决定了系统启动之后运行于什么级别。运行级别决定了系统启动的绝大部分行为和目的。这个级别从0到 6 ,具有不同的功能。不同的运行级定义如下:# 0 - 停机(千万别把initdefault设置为0,否则系统永远无法启动)# 1 - 单用户模式# 2 - 多用户,没有 NFS# 3 - 完全多用户模式(标准的运行级)# 4
7、 系统保留的# 5 - X11 (x window)# 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包,这里面
8、就有很多对应的脚本。执行这些脚本可以用来启动,停止,重启这些服务。前面说到,/etc/rc.d/init.d这个目录下的脚本就类似与windows中的注册表,在系统启动的时候执行。程序运行到这里(init进程读取了运行级别),相信从命名的角度大家也能猜到该运行/etc/rc.d/init.d里面的脚本了,不然它为什么也叫init(.d)呢是吧。没错,是该运行init.d里的脚本了,但是并不是直接运行,而是有选择的因为系统并不需要启动所有的服务。那么,系统是如何选择哪些需要启动哪些不要呢?这时刚才说的运行级别就起作用了。在决定了系统启动的run level之后,/etc/rc.d/rc这个脚本先
9、执行。在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里真正被执行的
10、脚本的文件名之后,一直有几个问题没弄明白。借着写这个文章的机会,我做了一些功课,总算是大概解开了那些疑惑。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后面带的数字呢?干什么用的这个我开始的时候还以为是排列起来好看或者数数用呢。后来发现不是的。它的作用是用来排序,
11、就是决定这些脚本执行的顺序,数值小的先执行,数值大的后执行。很多时候这些执行顺序是很重要的,比如要启动Apache服务,就必须先配置网络接口,不然一个没有IP的机子来启动http服务那岂不是很搞笑。3、无意中我发现同一个服务带S的和带K的链接到init.d之后是同一个脚本。我就纳闷了,为什么会是执行同一个脚本呢?这个时候真是S和K的妙用了,原来S和K并不止是用来看起来分的清楚而已。S给和K还分别给init.d下面的脚本传递了start和stop的参数。哦,是这样的(焕然大悟的样子,呵呵)!这时我才想起来原来曾经无数用过的/etc/rc.d/init.d/network restart命令。原来
12、传S时相当于执行了/etc/rc.d/init.d/xxx start这条命令,当然K就相当于/etc/rc.d/init.d/xxx stop了.3. /init/main.c中init()函数init()函数的功能可分为4个部分:安装根文件系统;显示系统信息;运行系统初始资源配置文件rc中的命令;执行用户登录shell程序。代码首先调用系统调用setup(),用来收集硬盘设备分区表信息并安装根文件系统。在安装根文件系统之前,系统会先判断是否需要先建立虚拟盘若编译内核时设置了虚拟盘的人小,并在前面内核初始化过程中已经开辟了一块内存用作虛拟盘,则内核就会首先尝试把根文件系统加载到内存的虚拟盘区
13、中然后init()打开一个终端设备tty0,并复制其文件描述符以产生标准输入stdin、标准输出stdout和错误输出stderr设备。内核随后利用这些描述符在终端上显示一些系统信息,例如高速缓冲区中缓冲块总数、主内存区空闲内存总字节数等。接着init()又新建了一个进程(进程2),并在其中为建立用户交互使用环境而执行一些初始配置操作,即在用户可以使用shell命令行环境之前,内核调用/bin/sh程序运行了配置文件/etc/rc中设置的命令。rc文件的作用与DOS系统根目录上的AUTOEXEC.BAT文件类似。这段代码首先通过关闭文件描述符0,并立刻打开文件/etc/rc,从而把标准输入st
14、din定向到/etc/rc文件上。这样,所有的标准输入数据都将从该文件中读取。然后内核以非交互形式执行/bin/sh,从而实现执行/etc/rc文件中的命令。当该文件中的命令执行完毕后,/bin/sh就会立刻退出。因此进程2也就随之结束。init()函数的最后一部份用于在新建进程中为用户建立一个新的会话,并运行用户登录shell程序/bin.sh在系统执行进程2中的程序时,父进程(init进程)一直等待着它的结束。随着进程2的退出,父进程就进入到一个无限循环中。在该循环中,父进程会再次生成一个新进程,然后在该进程中创建一个新的会话。并以登录shell方式再次执行程序/bin/sh,以创建用户交
15、互shell环境。然后父进程继续等待该于进程。登录shell虽然与前而的非交互式shell是同一个程序/bin/sh,但是所使用的命令行参数(argv)不同。登录shell的第0个命令行参数的第1个字符一定是一个减号-。这个特定的标志会在/bin/sh执行时通知它这不是一次普通的运行,而是作为登录shell运行/bin/sh的。从这时开始,用户就可以正常使用Linux命令行环境了,而父进程随之又进入等待状态此后若用户在命令行上执行了exit或logout命令,那么在显示一条当前登录shell退出的信息后,系统就会在这个无限循环中再次重复以上创建登录shell进程的过程。以下是init/main
16、.c中的关于init()函数的源代码:void init(void) int pid,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,ar
17、gv_init,envp_init); /* if this fails, fall through to original stuff */ if (!(pid=fork() close(0); if (open(/etc/rc,O_RDONLY,0) _exit(1); execve(/bin/sh,argv_rc,envp_rc); _exit(2); if (pid0) while (pid != wait(&i) /* nothing */; while (1) if (pid = fork() (reserved) 0.000000 last_pfn = 0x40000 max_a
18、rch_pfn = 0x100000 0.000000 MTRR default type: uncachable 0.000000 MTRR fixed ranges enabled: 0.000000 00000-9FFFF write-back 0.000000 A0000-BFFFF uncachable 0.000000 C0000-CBFFF write-protect 0.000000 CC000-EFFFF uncachable 0.000000 F0000-FFFFF write-protect 0.000000 MTRR variable ranges enabled: 0
19、.000000 0 base 0000000000 mask 00C0000000 write-back 0.000000 1 disabled 0.000000 2 disabled 0.000000 3 disabled 0.000000 4 disabled 0.000000 5 disabled 0.000000 6 disabled 0.000000 7 disabled 0.000000 PAT not supported by CPU. 0.000000 - cut here - 0.000000 WARNING: at /build/buildd/linux-2.6.32/ar
20、ch/x86/kernel/cpu/mtrr/generic.c:467 generic_get_mtrr+0xeb/0x100() 0.000000 Hardware name: VMware Virtual Platform 0.000000 mtrr: your BIOS has set up an incorrect mask, fixing it up. 0.000000 Modules linked in: 0.000000 Pid: 0, comm: swapper Not tainted 2.6.32-22-generic #36-Ubuntu 0.000000 Call Tr
21、ace: 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_
22、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 - end trace a7919e7f17c0a725 - 0.000000 Scanning 0 areas for lo
23、w memory corruption 0.000000 modified physical RAM map: 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
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1