linux 系统启动流程

假设以个人架设的linux主机为例:当你按下电源键之后,计算机硬件会主动读取BIOS来加载硬件信息及进行硬件系统的自我测试,之后系统会主动读取系统第一个可启动的设备,此时就可以读入引导装载程序了。

引导程序可以指定使用哪个内核文件来启动,并实际加载内核到内存中解压缩与执行,此时内核就能够开始在内存内活动,并检测所有硬件信息,与加载适当的驱动程序来使这部主机开始运行,等到内核检测硬件与加载驱动程序之后就可以启动系统了。

linux系统的启动流程如下:

1、 加载BIOS的硬件信息与进行自我测试,并依据设置取得第一个可启动的设备。

       boot Sequence:按次序查找各引导设备,第一个有引导程序的设备即为本地启用要用到的设备   (BIOS) 

2、 读取执行第一个启动设备内MBR的Bootloader(grub)    

                Boot Loader的功能:要认识操作系统的文件格式,并根据这个加载内核到内存中去执行。

                MBR是整个硬盘的第一个扇区内的一个块,充其量整个大小也有446,要加载boot的分区的驱动程序,ll -h `locate *ext4.ko`可以看到驱动程序有631k,因此446个字节根本装不下,不能加载驱动程序,因此linux将boot loader的程序代码执行与设置分为两个阶段:

                                阶段1、446个字节,不属于任何一个分区,他是硬盘上面第一个扇区,也没有文件系统,不需要驱动,

                                阶段1.5、位于第一个扇区后面的扇区,用于存放/boot分区的文件系统的驱动程序,因为/boot是被ext4格式化的,因此需要驱动程序,才能该分区,/boot/grub/*,可以看到1.5阶段的一些文件(备份使用)(fdisk -l 可以看到分区是从第一个柱面开始分的,所以还有0柱面8M的空间,用于存放这些数据,所以空间非常充裕 hexdump -C -n 15000 /dev/sda)。

                                阶段2、挂载/boot目录,加载内核文件,加载虚拟文件系统,挂载根文件系统,就是第三步所实现的功能,2st及内核等通常放置于一个基本磁盘分区(非raid,非lvs等/boot目录可以单独分区,如果想把根做成raid等非基本磁盘分区)。

                grub功能:提供一个菜单,允许用户选择要启动的系统或不同的内核版本,把用户选定的内核版本装载到RAM中的特定空间中,解压,展开,而后把系统控制权移交给内核

3、 依据Bootloader的设置加载Kernel文件到内存中,Kernel会开始检测硬件与加载驱动程序(此时接管bios工作)。

                内核文件:/boot/vmlinuz-2.6.32-642.el6.x86_64

                驱动程序:/lib/modules/

                            该文件存在磁盘上,内核需要加载磁盘驱动,才能挂载根目录,访问驱动程序,所以此时根根本无法挂载,因此就需要一个虚拟文件系统文件

                虚拟文件系统文件:/boot/initramfs-2.6.32-642.el6.x86_64.img

                            在内存中解压成一个伪根文件系统,内核借此加载适当的驱动程序,最总释放虚拟文件系统,并挂载实际根目录文件系统。

                            通过/bootloader加载到内存中,然后在内存中仿真成一个根目录,且此仿真在内存中的文件系统能够提供一个可执行程序,通过该程序来加载启动过程中所最需要的驱动程序    (USB,raid,lv,scsi等),等载入完成之后,内核就能识别真正的根了,然后进程根切换,切换完成后,调用/sbin/init来开始后续的正常启动流程。

                              该文件的查看方法:有file initramfs-2.6.32-642.el6.x86_64.img可以看到该文件是压缩文件因此:

                                       1、mv initramfs-2.6.32-642.el6.x86_64.img initramfs-2.6.32-642.el6.x86_64.img.gz

                                            gzip -d initramfs-2.6.32-642.el6.x86_64.img.gz

                                            cat initramfs-2.6.32-642.el6.x86_64.img | cpio -id 

                                       2、zcat initramfs-2.6.32-642.el6.x86_64.img | cpio -id 

                            该文件删除后的恢复方法:            

                                                        1、救援模式

                                                        2、chroot /mnt/sysimage  切换根  救援模式的工具比较少 因此切换到根

                                                        3、mkinitrd /boot/initramfs-`uname -r`.img   `uname -r`  此操作要在/boot目录下运行

                                                        4、exit;exit;reboot

4、 在硬件驱动成功后,Kernel会主动调用init进程,而init进程会取得run-level信息

                     Init:准备软件执行环境,包括系统主机名,网络设置,文件系统格式及其他服务的启动等。

                     配置文件:/etc/inittab,在配置文件有一个重要的设置,就是默认run-level 

5、 Init 执行/etc/rc.d/rc.sysinit文件来准备软件执行的操作环境,配合好整个系统(如网络,时区)

                            功能:
                                        1、设置主机名:
                                        2、设置欢迎信息
                                        3、激活udey和selinux
                                        4、挂载/etc/fstab文件中的定义的所有文件系统
                                        5、检测根文件系统,并以读写方式重新挂载根文件系统

                                        6、设置系统时钟;
                                        7、根据/etc/sysctl.conf文件的设定,来设定内核参数;
                                        8、激活lvm及软raid
                                        9、激活swap设备
                                        10、加载额外设备的驱动程序;
                                        11、清理操作;

6、 启动核心的外挂模块(/etc/modprobe.conf)

                  用户加载自定义模块的驱动程序,通常该文件可以自行产生。

7、 Init运行runl-level的各个服务的启动(script方式)

                运行级别:为了系统运行或维护的目的而设定的机制

                          0-6:7个级别

                          0:关机shutdown

                          1:单用户模式(single user),root用户,无需认证,维护模式

                          2、多用户模式(multi user),会启用网络功能,但不会启动NFS;维护模式

                          3、多用户模式(mutli suer),完全功能模式;文本界面;

                          4、预留级别:目前无特别适用目的,但习惯以同3界别使用;

                          5、多用户级别(multi user),完全功能模哦;

                               6、重启模式,reboot

                  centos 6中/etc/inittab设置的默认级别为:

                                       id:5:initdefault:

                         其中:

                                id:runlevels:action:process

                                id:一个任务的标识符

                                 runlevels:在哪些级别下启用此任务;

                                action:在什么条件下启动此任务;

                                process:任务

                          action:

                                wait:等待切换至此任务所在的级别时执行一次;

                                  respawn:一旦此任务终止时,就会重新启动

                                   initdefault:设定默认运行级别;此时process会省略

                                   sysinit:设定系统初始化方式,此处一般指定/etc/rc.d/rc.sysinit脚本;

 

                    启动对应级别下的服务(看默认级别,如果默认级别是5 就运行5下面的程序):

                                   0:0:wait:/etc/rc.d/rc 0

                                       。。。。

                                   11:0:wait:/etc/rc.d/rc 5

                                   12:0:wait:/etc/rc.d/rc 6

                              init要读取/etc/inittab配置文件完成初始化,该配置文件中有一堆的/etc/rc.d/rc 0,每个级别都有分别做了定义,他会等到你切换到该级别上来,切换过来后,init会到该级别下,将所有k开头的文件stop掉,所有s启动起来,这就是有些服务开机自动能启动的原因。Fl,rc5.d 目录下面的文件都是软连接,对应的都是/etc/init.d/下面对应的服务脚本,且配置文件在/etc/sysconfig/目录下,rc5.d目录下都是以k或者s打头的,后面跟的数字代表执行的顺序,且是以字符进行排序,表示执行的优先级。

                     当然我们也可以自定义/etc/inittab中的服务:

                                例如:

                                                             1、进入/etc/init.d下建立脚本

                                                                    #!/bin/bash

                                                                    #chkconfig:35 88 22

                                                                    #description:test service 

                                                                        echo "How are you?"

                                                              2、chmod +x testrv

                                                              3、chkconfig –add testsrv

                                                              4、chkconfig –list testsrv

                                                                                    testrv    0:关闭 1:关闭 2:关闭 3:启用 4:启用 5:启用 6:关闭

                                                              5、service testsrv

                                                              6、chkconfig –del testsrv

                                                            注意:chkconfig [–level <levels>] [–type <type>] <name> <on|off|reset|resetpriorities>

8、 Init执行/etc/rc.d/rc.local文件

                             目录下中的/rc.local脚本,我们有任何启动时就要运行的脚本可以写到该文件中,在开机启动的时候就会自动被加载。

9、 Init执行终端机模拟程序mingetty来启动login进程,最后等待用户登录

10、登录后开始以shell控制合主机。

POST –> Boot Sequence (BIOS) –> Boot Loader (MBR) –> kernel(ramdisk) –rootfs –> switchroot    –> /sbin/init –>(/etc/init/*.conf,/etc/inittab) –> 设定默认运行级别 –> 运行系统初始化脚本 –> 关闭或启动对应级别下的服务 –> 启动终端

内核模块的增删查

    目前内核都是具有可读取模块化驱动程序的功能,我们也可以理解为驱动程序,那么到底目前内核中加载了多少模块呢?

    lsmod:查询内核中加载的模块 常配合grep使用

                    Module                  Size  Used by                    
                    nls_utf8                1455  1 
                    fuse                   79892  2 
                    rfcomm                 71079  4 
                    sco                    17493  2 
                    bridge                 85674  0 
                    
                    模块名称           模块大小   此模块是否被其他模块所使用

    modinfo:查询模块信息

        格式:modinfo [-adln] [module_name][filename]

        选项:

                        -a:仅列出作者名称

                        -d:仅列出该modules的说明

                         -l:仅列出授权

                        -n:仅列出该模块的详细路径

    insmod:加载内核模块(需要用户自行加载一个完整文件名的模块)

        格式:insmod [/full/path/module_name][parameters]

                            insmod /lib/modules/$(uname -r)/kernel/fs/cifs/cifs.ko(必须要完整的文件名)

    modprobe:加载内核模块

        格式:modprobe [-lcfr] module_name

        选项:

                        -c:列出目前系统所有模块

                        -l:列出目前在/lib/modules/`uname -r`/kernel 当中的所有模块完整文件名

                        -f:起那个会加载模块

                        -r:类似rmmod,就是删除某个模块

    rmmod:删除模块

        格式:rmmod [-fw] module_name

        选项:

                        -f:强制将模块删除掉,不管是否使用

                        -w:若该模块正被使用,则rmmod会等待该模块被使用完毕后才删除他

   

原创文章,作者:Naruto,如若转载,请注明出处:http://www.178linux.com/45390