写在前面:

    博客书写牢记5W1H法则:What,Why,When,Where,Who,How。


本篇主要内容:

● 启动相关基础概念汇总

启动流程

● init程序类型

    /etc/rc.d/rc

    chkconfig

    /etc/rc.d/rc.sysinit

● GRUB legacy

    命令行接口

    配置文件

● Linux Kernel

    内核模块查看与管理

        lsmod

        modinfo

        modprobe

        insmod/rmmod

        depmod

    ramdisk文件管理

        mkinitrd

        dracut

    内核输出伪文件系统

        /proc

            /proc/sys及内核参数修改

        /sys



基础概念汇总:

   Linux内核功能:

      进程管理、网络协议栈(如IP信息)、文件系统管理、驱动程序、安全功能(selinux等)

   内核流派:

      Linux内核为单内核设计,各功能之间的沟通更加高效,同时也参考了微内核设计结构灵活的特点,对内核的诸多功能实行模块化设计,以完成动态装载特定功能。

   MBR:

      Master Boot Record

      占用硬盘的第一个扇区,即512bytes

         446bytes:装载boot loader

         64bytes:硬盘分区表

         2bytes:标识字符,确认硬盘是否完好。一般存储内容为55AA

   其他分区类型:UEFI+GPT

   多系统:

   无论每个文件系统都会在首部保留一块启动扇区(boot sector)提供给操作系统安装boot loader,然后操作系统在安装时会在MBR中也写入boot loader。开机时可以根据MBR中的boot loader条目来直接启动系统内核,也可以将控制权交给另一个boot分区上的boot loader。从而实现多系统。

wKioL1b3xoLgw0qiAAAZK8P0uYQ517.png


   启动流程:

      1.硬件加电,系统加载BIOS(Basic Input Output System)

      2.透过BIOS加载CMOS信息,根据CMOS的设定值获得主机的各硬件配置,如:CPU与接口设备的沟通频率、开机装置的搜寻顺序、硬盘大小与类型、系统时间、是否启用即插即用设备(PnP)等等

      3.开机自检(Power On Self Test)POST:开始执行硬件侦测的初始化,设定PnP装置,之后根据开机装置顺序,开始进行开机装置数据读取。

      4.BIOS会以特殊方式来读取MBR(Master Boot Record,主引导记录),所以MBR中的boot loader也会被识别。

      boot loader的主要功能是要识别操作系统的文件格式并据以加载核心到主存储核心去执行。

         对windows而言,boot loader是ntloader;

         对linux而言,boot loader是LILO(LInux LOader)或GRUB(GRand Uniform Bootloader)

      boot loader的主要功能:

         (1)提供选单。Title List

         (2)载入核心文件,将系统控制权移交给内核。

         (3)转交其他loader。将开机管理功能移交给其他loader负责。

      补充:boot loader也可以识别硬盘上的分区,并读取分区上的文件,所以才能够加载内核。但其识别硬盘的方式与我们平时不太一样,参考下面grub配置。

      5.boot loader将系统控制权交给内核。

         (1)内核完成自身初始化:

         (2)探测可识别的所有硬件设备,而不是使用BIOS的结果,此时内核完全接管了开机任务,与BIOS无关了;

         (3)加载硬件驱动程序;(可能借助ramdisk)

         (4)以只读方式挂载根文件系统;

         (5)运行用户空间第一应用程序/sbin/init

         注意:

            内核挂载根文件系统的时候需要磁盘驱动程序,而磁盘驱动程序在/lib/modules目录下,这样就永远无法挂载硬盘了。

            为了解决这个问题,centos透过grub加载虚拟文件系统(Inital RAM DISK,/boot/initrdramfs-$(uname -r).img文件)到内存中,ramdisk能够为核心提供开机所需的核心模块、文件系统与磁盘接口驱动程序,这样内核就能够识别真正的根文件系统了(由于ramdisk提供了lvm、RAID驱动,所以即使/在lvm或raid分区也可以识别),并帮助核心重新载入第一应用程序来开始后续正常开机。

            当内核识别到硬盘后,会chroot到硬盘所在/,而后完成正常启动了。

            补充:我们也可以直接将硬盘模块编译进内核中,而不是放到/lib/modules目录动态加载。这样即使没有randisk文件,也是可以正常开机的。

      6.系统启动初始化流程

         centos5.x:

         脚本机制:

            (1)init程序(/sbin/init)根据/etc/inittab定义的默认运行级别设置运行级别

            (2)运行系统初始化脚本/etc/rc.d/rc.sysinit,完成系统初始化

            (3)通过/etc/rc.d/rc脚本关闭对应级别需要停止的服务,启动需要开启的服务

            (4)设置登录终端

            (5)如果运行级别为5,启动图形终端

         centos6.x:

            使用upstart风格的配置文件来调用脚本机制的脚本

         centos7.x

            使用systemd来管理所有的系统初始化、需开启或关闭的服务、设置登录终端、图形终端。


init程序的类型:

   1、CentOS 5-:SysV init

      /sbin/init

      配置文件:/etc/inittab 

      运行级别(runlevel):

         0-6的数字表示7个运行级别:

            0:关机,shutdown

            1:单用户模式,single user

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

            3.多用户模式,multi user,完全功能,文本界面模式

            4.预留界别,目前无特别使用目的,习惯以同3级别功能使用

            5.多用户模式,multi user,完全功能,图形界面模式

            6.重启,reboot

      默认级别:

         3、5

      级别切换:

         init #

      运行级别查看:

         who -r

         runlevel

            输出2个字符串,第一个为上次运行级别,N表示无,第二个为当前运行级别。

      配置文件格式:

         /etc/inittab

         每行定义一种action和对应的process

            id:runlevel:action:process

               id:任务标识,随意写

               runlevel:指定切换到哪个运行级别时执行后面的action和process。空表示所有级别

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

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

                  respawn:一旦此任务终止,就自动重新启动;

                  initdefault:设定默认运行级别,process项省略;

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

               process:任务

      例如:

#设置默认运行级别
id:3:initdefault: 
#设置系统初始化执行的脚本文件
si::sysinit:/etc/rc.d/rc.sysinit
#设置切换到某级别时,使用rc脚本完成服务启动与关闭
l0:0:wait:/etc/rc.d/rc  0
l1:1:wait:/etc/rc.d/rc  1
…………
l6:6:wait:/etc/rc.d/rc  6
#打开终端
tty1:2345:respawn:/usr/sbin/mingetty tty1
... ...
tty6:2345:respawn:/usr/sbin/mingetty tty6


   2、CentOS 6:Upstart

      仍然为/sbin/init

      配置文件:/etc/inittab(仅用来定义默认运行级别)

         /etc/init/*.conf

      注意:/etc/init/*.conf文件为upstart风格的配置文件;完全兼容centos5的方式。

         其中

            rcS.conf 配置系统初始化

            rc.conf  配置对应级别服务开启与关闭

            start-ttys.conf  配置打开终端


   3、CentOS 7:Systemd

      配置文件:/usr/lib/systemd/system/*, /etc/systemd/system/*

      systemd完全兼容SysV脚本机制,因此service命令依旧可用;但建议使用systemctl命令来控制服务。



/etc/rc.d/rc

   这是一个脚本文件,用来控制运行级别切换时的服务开启与关闭。

   此脚本会根据/etc/rc.d目录中rc#.d目录下以K或S开头的链接文件来确定开启或关闭某项服务

      如:S90crond、K92iptables

      S开头的为开启

      K开头的为关闭

      S或K后面的数字表示运行的先后顺序,数字越小越优先运行

      数字后面的内容为服务名称,是/etc/rc.d/init.d目录下存在的脚本文件名称。脚本文件开头定义了默认运行级别(在哪些级别开启)、开启顺序(S开头后跟的数字)、关闭顺序(K开头后跟的数字)。


chkconfig

   chkconfig命令会在/etc/rc.d/rc#.d目录中创建链接文件,以供/etc/rc.d/rc脚本完成运行级别切换时要启动或关闭的服务。

   #添加管理的服务:

      chkconfig --add SERVICE

      会根据/etc/rc.d/init.d目录下的SERVICE文件的开头定义内容在/etc/rc.d/rc#.d目录中生成对应的链接文件。如:

         /etc/rc.d/init.d/crond文件开头内容:# chkconfig: 2345 90 60

         则通过执行chkconfig --add crond命令后,会在/etc/rc.d/rc2.d、rc3.d、rc4.d和rc5.d目录中分别生成S90crond链接文件。而在/etc/rc.d/rc0.d、rc1.d和rc6.d目录中生成K60crond链接文件。

   #删除管理服务:

      chkconfig --del SERVICE

      /etc/rc.d/目录下有一个特殊文件rc.local,它也会在/etc/rc.d/rc2、3、4、5.d目录中生成链接文件,所以当需要在2、3、4、5级别运行某服务时,可以编辑此文件。

   #修改某运行级别开启、关闭某服务,默认为2345

      chkconfig [--level <levels>] <name> <on|off|reset|resetpriorities>


/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) 清理操作; 


GRUB(GRand Unified Bootloader)

   目前有两个版本

      grub 0.x:grub legacy,centos5.x/6.x使用

      grub 1.x:grub2,centos7.x使用

   grub legacy:

      由于MBR中只有446bytes给boot loader使用,无法存储太多信息,所以grub legacy将程序代码执行与设定值分成2个步骤(stage)

      stage1:执行装载在mbr中的程序代码

      stage2:通过/boot/grub/目录中的配置文件配置:

         (1)提供菜单、并提供交互式接口

            e:编辑菜单

            c:交互式命令接口

         (2)加载用户选择的内核或操作系统

            允许传递参数给内核

            可隐藏菜单

         (3)为菜单提供保护机制:

            为编辑菜单进行认证

            为启用内核或操作系统进行认证。

      存储设备识别

         (hd#,#)

            hd#:所有设备均识别为hd,根据识别的顺序从0开始编号

            #:分区编号,从0开始

      命令行接口:

         grub> help [KEYWORD]

         grub> find (hd#,#)/FILE

         grub> root (hd#,#)

         grub> kernel /vmlinuz-2.6.32.573.e16.x86_64 root=/dev/mapper/vg0-root [附加选项]

            ro quiet init=/PATH/TO/INIT selinux=0

         grub> initrd /initramfs-2.6.32.573.e16.x86_64.img

         grub> boot

         注意:

            由于我们将boot分区设置为/,所以对应的路径下文件也会与linux系统上不同:

               如果/boot/分区是单独分区,则/boot/ --> /

               如果/boot/分区未单独分区,则/boot/ --> /boot/

      配置文件:

         /boot/grub/grub.conf

            default=#: 设定默认启动的菜单项;(title项)编号从0开始;

            timeout=#:指定菜单项等待选项选择的时长;

            splashp_w_picpath=(hd#,#)/PATH/TO/XPM_PIC_FILE:指明菜单背景图片文件路径;

            hiddenmenu:隐藏菜单;

            password [--md5] STRING: 菜单编辑认证;

            title TITLE:定义菜单项“标题”, 可出现多次;

               root (hd#,#):grub查找stage2及kernel文件所在设备分区;为grub的“根”; 

               kernel /PATH/TO/VMLINUZ_FILE [PARAMETERS]:启动的内核

               initrd /PATH/TO/INITRAMFS_FILE: 内核匹配的ramfs文件;

               password [--md5] STRING: 启动选定的内核或操作系统时进行认证;

         补充:

            当使用password条目时,可以使用--md5来指明密码为md5加密密码,而加密密码字符串可以使用grub-md5-crypt命令生成。


开机进入单用户模式:

   (1) 编辑grub菜单(选定要编辑的title,而后使用e命令); 

   (2) 在选定的kernel后附加

      1, s, S或single都可以;

   (3) 在kernel所在行,键入“b”命令;


安装grub:

   以下两种方式必须依赖启动的系统:

      (1)grub-install命令安装

         grub-install --root-directory=ROOT /dev/DISK

         root-directory指的是boot目录的父目录

      (2)grub命令行安装

         > root (hd0,0)

         > setup (hd0)


Linux Kernel


ldd

   print shared library dependencies

   查看程序(命令)依赖的库文件


内核的组成部分:

   kernel

      内核核心,一般为bzImage格式,通常位于/boot/目录,名称为vmlinuz-VERSION-release;

   kernel object:

      内核对象,即内核模块,通常放置在/lib/modules/VERSION-release/目录

      注意:内核模块与内核核心版本必须严格匹配

      补充:内核编译时对部分功能的选项:

         [ ]:N,不编译此模块;

         [M]:Module,编译为模块,动态加载

         [*]:Y,编译进内核核心中

   ramdisk:

      辅助性文件,简装版的根文件系统,非必须,这取决于内核是否能直接驱动rootfs所在的设备(包括目标设备驱动、逻辑设备驱动、文件系统驱动)。


查看内核信息:

   uname

      -r:内核release号

      -n:主机名


内核模块获取与管理:

   lsmod

      Show the status of modules in the Linux Kernel

      显示已经加载到内核中的内核模块的状态信息。

      输出含义:

         模块名称 大小 被引用次数以及被谁引用

   modinfo

      Show information about a Linux Kernel module

      modinfo [-F field] [-k kernel] [modulename|filename...]

      -F field: 仅显示指定字段的信息;

      -n:显示文件路径;

      需要注意的是,输出中有一行“depends:”项,表示此模块依赖的其他模块名称。

   modprobe

      Add and remove modules from the Linux Kernel

      动态装载模块:

         modprobe module_name 

      动态卸载模块:

         modprobe -r module_name

      注意:当装载的模块依赖其他模块时,其他模块会被自动安装。

   其他装载与卸载模块命令:

      insmod

         insmod [module_path] [options]

      rmmod

         rmmod [module_name]

      这组命令需要手动解决模块依赖关系

   depmod

      depmod [module_path]

         内核模块依赖关系文件的生成工具。这些信息存放在/lib/modules/`uname -r`/目录下


ramdisk文件管理:

   (1)mkinitrd

      为当前使用中的内核重新生成ramdisk文件

      mkinitrd [OPTION...] [<initrd-p_w_picpath>] <kernel-version>

         --with=<module>:指定除默认模块外,额外装载只initramfs的模块

         --preload=<module>:initramfs所提供的需要预先装载的模块

      实例:

         ~]# mkinitrd  /boot/initramfs-$(uname -r).img   $(uname -r)

   (2)dracut

      底层的创建initramfs的工具,其实mkinitrd就是调用的此命令。

         dracut [OPTION...] [<p_w_picpath> [<kernel version>]]

      实例: 

         ~]# dracut /boot/initramfs-$(uname -r).img  $(uname -r)


内核输出的伪文件系统:

   /proc

      内核状态和统计信息的输出接口;同时也提供一个配置接口/proc/sys/

      /proc/sys/

         此目录下的net/ipv4/ip_forward相当于net.ipv4.ip_forward

         值的查看与设定:

            (1)sysctl命令

               专用于查看或设定/proc/sys/目录下的参数的值;

               sysctl [options] [variable[=value]]

               查看:

                  sysctl -a

                  sysctl variable

               修改:

                  sysctl -w variable=value

            (2)使用cat、echo等命令重定向到文件

               查看:

                  cat /proc/sys/PATH/TO/KERNEL_FILE

               修改:

                  echo "VALUE" > /proc/sys/PATH/TO/KERNEL_FILE

            (3)配置文件

               /etc/sysctl.conf、/etc/sysctl.d/*.conf

               使其立即生效:

                  sysctl -p [CONFIG_FILE]

         常见内核参数:

            net.ipv4.ip_forward:核心转发;

            vm.drop_caches:内存缓存配置

            kernel.hostname:主机名;

            net.ipv4.icmp_echo_ignore_all:忽略所有ping操作;

   /sys

      开机完成后,内核会输出识别到的硬件设备信息到/sys目录。

      sysfs:输出内核识别出的各硬件设备的相关属性信息,也有内核对硬件特性的可设置参数;对此些参数的修改,即可定制硬件设备工作特性;

      udev:通过读取/sys目录下的硬件设备信息按需为各硬件设备创建设备文件;udev是用户空间程序,不能直接操作硬件,所以需要借助/sys中的文件;

         专用创建dev的工具:devadmin, hotplug;

         udev为设备创建设备文件时,会读取其事先定义好的规则文件,一般在/etc/udev/rules.d/目录下,以及/usr/lib/udev/rules.d/目录下;