彼岸船夫

我是一只菜鸟,在繁华城市独自飞翔,为生活有时候很迷茫,苦苦坚持在无烟沙场,期待渡船远方

Centos启动流程及grub legacy

Linux系统的组成部分:内核+根文件系统
内核的功能:进程管理、内存管理、网络管理、文件系统、驱动程序、安全功能

系统在运行时要么就是在运行内核代码,要么就是在运行应用程序代码。如果一个程序大多数时间在内核的系统调用上,那样真正执行业务功能的时间就少了,实际生产力不大。通常在开发程序的时候,大都不是直接使用系统调用来实现功能,而是使用系统调用的二次封装(glibc库),所谓库,就是函数(功能)的集合,库中的函数名,能够接受的参数,参数类型都应该有定义(头文件)。

库也是二进制程序,但是相比正常程序而言,库没有执行入口,只能通过被调用才能实现功能。进一步划分库,分为是否有返回结果,称之为过程调用和函数调用。

所以系统的最基本组成就是内核、程序、库。为了运行程序就必须要文件系统。

内核作为操作系统的最核心有两种设计流派:
        单内核设计:把所有功能集成于同一个程序;Linux
        微内核设计:每种功能使用一个单独的子系统实现;Windows, Solaris,微内核设计才能真正实现线程
       
Linux内核特点:
        借鉴了微内核设计,支持模块化:  .ko (kernel object),类似于库(.so)是被程序调用。
        支持模块运行时动态装载或卸载;
           
内核组成部分:
         核心文件:/boot/vmlinuz-VERSION-release
         ramdisk:
                    CentOS 5:/boot/initrd-VERSION-release.img
                    CentOS 6,7:/boot/initramfs-VERSION-release.img
         模块文件:/lib/modules/VERSION-release
        现有一种情景,内核启动后需要加载各个硬件的驱动程序,但是内核不可能包含所有硬件的驱动,因为内核的功能都是模块文件来实现的,然而内核模块/lib/modules/的目录是在文件系统上,所以要使用这个目录的模块就需要正确识别磁盘和文件系统,就需要有正确的驱动,可是驱动模块又在磁盘上。如何解决这个矛盾,就出现了ramdisk(内存模拟的磁盘)文件,是一个微型的文件系统,里面存放了内核为了访问磁盘和文件系统等基本设备的驱动,这样内核就可以真正的访问磁盘上的模块文件。

ramdisk是安装系统的最后一步动态生成的,只存在用于识别当前硬盘的驱动文件,这个文件并不会把所有的驱动都包含。
在Centos 6开始称之为initramfs(内存模拟的文件系统),因为内核特性使得硬盘读取数据的时候会先在内存设立缓存区,然后再从内存缓存区读取,但是本身这个ramdisk的内容已经在内存中了,造成了二次缓存,就没有必要从内存读取到内存缓存了。

CentOS 系统的启动流程
系统初始化流程(内核级别): POST --> BootSequence(BIOS) --> BootLoader(MBR)--> Kernel(ramdisk)--> rootfs(readonly)--> /sbin/init ()。完整的详细启动过程参照 CentOS系统启动流程

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

GRUB启动的阶段:
        bootloader:1st stage,这个阶段作用只有一个,就为了找到stage 2
        stage 1.5:位于分区文件系统,因为stage 2 在磁盘分区上,要正确识别分区文件系统。位于MBR后面的扇区。
        stage 2:位于文件系统/boot/grub

Kernel自身初始化:
        探测可识别到的所有硬件设备;
        加载硬件驱动程序;(有可能会借助于ramdisk加载驱动)
        以只读方式挂载根文件系统;
        运行用户空间的第一个应用程序:/sbin/init(Centos5、6、7使用的都不同)

init程序的类型:
        CentOS 5-:SysV init
         配置文件:/etc/inittab
                       
        CentOS 6:Upstart
          配置文件:/etc/inittab; /etc/init/*.conf
                           
        CentOS 7:Systemd
          配置文件:/usr/lib/systemd/system/, /etc/systemd/system/

ramdisk/ramfs生成的工具程序:
        CentOS 5: initrd  工具程序:mkinitrd
        CentOS 6,7: initramfs  工具程序:dracut, mkinitrd(一般不用)


init

运行级别

假设一种场景,在Windows上安装了不兼容硬件的驱动导致一启动就蓝屏。那么正常情况只要卸载了此驱动就能正常启动。然而启动就蓝屏使得根本无法卸载。这个时候Windows就有了一个安全模式,安全模式下只加载了基本的系统组件,与正常启动相比这种模式下加载了不同的驱动启动了不同的服务。使得系统异常时有一个基本的环境来进行维护工作。

在linux中也同样有这种用于维护的模式,称之为运行级别(Centos5/6存在)。由init程序管理,在不同的级别下启动不同的服务和程序。

运行级别有7个:
         0:关机
         1:单用户模式(root用户无需登陆),single,用于维护
         2:多用户模式,启动网络功能,但是不启动网络文件系统,用于维护
         3:多用户模式,正常启动,文本界面
         4:多用户模式,预留的级别,同级别3.
         5:多用户模式,正常启动,图形界面
         6:重启
所以一般常用于系统启动的有3、4、5。

级别的切换通过init程序:init  level
查看级别:runlevel 、who –r

init的配置文件为/etc/inittab。按照指定格式id:runlevel:action:process

以Centos5为例:

        id:3:initdefault:
        si::sysinit:/etc/rc.d/rc.sysinit       #::表示所有级别

        id:作为唯一标识不可重复
        action:
            wait:切换到此级别执行一次
            initdefault:设置默认指定级别,process省略
            sysinit:设定初始化方式,一般运行/etc/rc.d/rc.sysinit,init依靠这脚本完成初始化

另外有:1:0:wait:/etc/rc.d/rc 1

当切换到级别1的时候执行rc脚本,并传递1,rc脚本读取rc1.d/*,该目录下两种文件

K##:传递stop,大致原理如下:
        for  srv  in  /etc/rc.d/rc0.d/K*;do
                $srv  stop
        done
S##:类似K,传递的是start
数字##标识启动的顺序。数字小的先执行,数字大小取决于依赖的服务。

为了方便管理启动的服务,有chkconfig 工具,自动在运行级别目录下创建链接,设置一个服务在某个级别下是K还是S。

想要一个服务可以通过chkconfig来控制,需要在服务启动脚本上使用如下标识
#chkconfig:  -  34   55

chkconfig命令:管控/etc/init.d/
chkconfig  --add | del  name
chkconfig  [--level  LEVELS]  name  <on|off|reset>

或者”###BEGIN  INIT  INFO   …….###END  INIT  INFO“这种格式

正常级别下有个S99local表示最后一个启动的脚本,指向/etc/rc.d/rc.local,用于自定义添加开机启动。

所有服务启动完成后,就会启动终端设备和登陆程序,同样在/etc/inittab的配置文件中定义(Centos6的配置文件就不止一个)
如:tty1:respanw:/usr/sbin/mingetty tty1

回到配置文件中,系统启动时sysinit执行的/etc/rc.d/rc.sysinit脚本进行了哪些操作。
        (1) 设置主机名;
        (2) 设置欢迎信息;
        (3) 激活udev和selinux;
        (4) 挂载/etc/fstab文件中定义的所有文件系统;
        (5) 检测根文件系统,并以读写方式重新挂载根文件系统;
        (6) 设置系统时钟;
        (7) 根据/etc/sysctl.conf文件来设置内核参数;
        (8) 激活lvm及软raid设备;
        (9) 激活swap设备;
        (10) 加载额外设备的驱动程序;
        (11) 清理操作;

完成内核加载后,启动第一个程序init的执行流程,/sbin/init (/etc/inittab)设置默认运行级别 --> 运行系统初始化脚本(rc.sysinit) --> 关闭对应级别下需要停止的服务,启动对应级别下需要开启的服务(rc #)--> 设置登录终端 (或启动图形终端)

以上关于init配置文件完成的功能适用于centos5,后续再比较这种启动过程的变革。

Centos 6的init程序就已经变为upstart,但是其命名依然为init。配置文件/etc/init/*.conf,同时兼容/etc/inittab(仅用于定义默认运行级别),但是*.conf 的配置文件是按照upstart的标准来定义的(比上一代要更加复杂)。

Centos7的init程序为systemd,启动服务的时候已经不像centos5那样使用shell脚本来启动服务。


GRUB

grub作为一个bootloader,实现的功能
(1) 提供菜单、并提供交互式接口
          e: 编辑模式,用于编辑菜单;
          c: 命令模式,交互式接口;
(2) 加载用户选择的内核或操作系统
          允许传递参数给内核
          可隐藏此菜单
(3) 为菜单提供了保护机制
          为编辑菜单进行认证
          为启用内核或操作系统进行认证

grub交互模式下的常用命令
        help: 获取帮助列表
        help KEYWORD: 详细帮助信息
        find (hd#,#)/PATH/TO/SOMEFILE:要指定磁盘分区
        root (hd#,#)  grub文件所在的分区设置为根
        kernel /PATH/TO/KERNEL_FILE: 设定本次启动时用到的内核文件;额外还可以添加许多内核支持使用的cmdline参数;
        例如:init=/path/to/init, selinux=0
        initrd /PATH/TO/INITRAMFS_FILE: 设定为选定的内核提供额外文件的ramdisk;
        boot: 引导启动选定的内核;

手动在grub命令行接口启动系统:
         grub> root (hd#,#)
         grub> kernel /vmlinuz-VERSION-RELEASE ro root=/dev/DEVICE
         grub> initrd /initramfs-VERSION-RELEASE.img
         grub> boot


配置文件:/boot/grub/grub.conf  配置启动时的菜单项
          default=#: 设定默认启动的菜单项;菜单项(title)编号从0开始;
          timeout=#:指定菜单项等待选项选择的时长;
          splashimage=(hd#,#)/PATH/TO/XPM_PIC_FILE:指明菜单背景图片文件路径;
          hiddenmenu:隐藏菜单;
          password [--md5] STRING: 菜单编辑认证;选择启动项的时候使用p按键输入密码。
          title TITLE:定义菜单项“标题”, 可出现多次;
                  root (hd#,#):grub查找stage2及kernel文件所在设备分区;为grub的“根”;
                  kernel /PATH/TO/VMLINUZ_FILE [PARAMETERS]:启动的内核
                  initrd /PATH/TO/INITRAMFS_FILE: 内核匹配的ramfs文件;
                  password [--md5] STRING: 启动选定的内核时进行认证;
          password放在title里面表示内核认证,放在外面表示编辑菜单需要认证
          grub-md5-crypt 用于生成md5加密后的密码

grub安装
        如果grub配置文件丢失,则启动时进入grub交互模式;如果grub的stage 1(MBR)损坏则无法启动任何系统。重新安装grub使用grub-install,这命令实现完全安装(stage1、stage1.5、stage2)
        grub-install --root-directory=ROOT /dev/DISK       #root-directory是指明包含boot目录的位置

grub修复
        假设场景MBR损坏,但是系统此时没有重启
        方法一:直接使用上述命令安装即可。
        方法二:直接输入grub命令进入交互模式。
        grub>root  (hd#,#)
        grub>setup  (hd0)       #指定是磁盘而非分区,这时会修复stage1,使用现有/boot目录下的stage1和stage1.5来修复

        如果无法损坏后无法开启系统,使用光盘进入救援模式,在救援模式下的bash-4.1# 执行grub-install,也可以切换/mnt/sysimage(原系统的根文件系统)来进行grub的安装

引导加载程序grub详解

 

posted on 2017-04-09 11:43  彼岸船夫  阅读(1289)  评论(0编辑  收藏  举报

导航