您的位置:首页 > 运维架构 > Linux

CentOS系列启动流程和内核原理(5系列,6系列,7系列)

2016-05-21 21:30 1071 查看
前言,本来让我写博客我是拒绝的

然而看见大家都在写,还能不能一起友好的玩耍了?


我要是不写怎能和同大神们一起ZB呢?遂开博客!




一、Linux启动内核文件

1.Linux系统组成

动态视角:内核+根文件系统

静态视角:磁盘分区+相关文件

2.Kernel特点

(1)支持某块化:.ko (kernel object)文件

centos7的ko文件:





centos6的ko文件:



注意:

Linux内核模块文件的命名方式通常为<模块名称.ko>

centos6系统的内核模块被集放在/lib/modules/'uname -r '/目录下

centos7系统的内核模块被集放在/usr/lib/modules/'uname -r '/目录下

(2)支持模块运行时动态装载或卸载;

模块的相关命令:

a)加载模块:insmod modprobe

insmod和modprobe的区别

当a模块与b模块有依赖关系时,假设安装b模块需先安装a模块。

如果用insmod命令那么需要先insmod a.ko 然后再insmod b.ko。

如果用modprobe命令那么直接可以modprobeb.ko。

其中/lib/modules/“内核版本号”/modules.dep中记录了模块之间的依赖关系。

通过modprobe加载的内核均在当前的计算机内有效,计算机重新启动后需要重新加载才有效。
如果想要开机后自动挂载内核,需要将modprobe命令写入/etc/rc.sysint文件中





b)卸载模块:rmmod modprobe -r

rmmod:只需要调用模块名即可,比如安装的时候是inmod a.ko 安装完毕后该模块存在于内核中的名字为a,那么卸载该模块只需要rmmod a即可。

[root@openstack01 ~]# modprobe ip_vs  #动态加载ip_vs模块
[root@openstack01 ~]# lsmod |grep ip_vs #查看模块是否加载成功
ip_vs                 125220  0
libcrc32c               1246  1 ip_vs
ipv6                  317340  289 ip_vs
[root@openstack01 ~]# modprobe -r ip_vs #卸载动态模块
[root@openstack01 ~]# lsmod |grep ip_vs #模块已经卸载干净


c)查看模块:lsmod

输出三列信息

分别为模块 占用内存 是否被调用

如果第三列为0则该模块可以随时可以卸载。





总结:Linux kernel在单内核设计模型上,吸取了多内核设计的优点,使用了模块化设计

单内核设计:把所有功能集成于同一个程序;如Linux

微内核设计:每种功能使用一个单独的子系统实现;如Windows,
Solaris

3.kernel组成

(1)核心文件

1)/boot/vmlinuz-VERSION-release

注: vmlinuz最后一一个z表示压缩格式的kernel文件





2)ramdisk(中间临时文件根系统,动态创建出来的,使用缓冲和缓存来加速对磁盘上的文件访问)

参考:Linux内核Ramdisk(initrd)机制

安装操作系统后临时生成的文件,能够扫描当前操作系统的硬盘驱动,装载对应的模块

用于实现系统初始化的基于内存的磁盘设备,把内存中的一段空间当内存使用

CentOS 5:/boot/initrd-VERSION-release.img

工具程序:mkinitrd

CentOS 6,7:/boot/initramfs-VERSION-release.img

工具程序:dracut,
mkinitrd

注意:

a)不是必须的,当自编译内核时候知道硬盘接口时候将硬盘驱动编译进kernel,ramdisk就不用了

b)initrd,基于ramdisk的磁盘映像文件;initramfs,基于ramdisk的文件系统

initrd启动该后用free查看memory时候,有一段空间被buffers和cached占用,二次缓存

从2.6内核开始,initrd.img采用cpio压缩,不再是2.4内核使用的ext2格式,无法使用mount -o loop 挂载。需要使用gunzip解压缩,然后再使用cpio解包

cpio命令:
cpio - copy files to and from archives
-i, --extract                Extract files from an archive (run in copy-in mode)
将打包文件解压或者将设备上的备份还原到系统。
-v, --verbose              Verbosely list the files processed
显示打包过程中的文件名称。
-o, --create                Create the archive (run in copy-out mode)
将文件拷贝打包成文件或者将文件输出到设备上。
-d, --make-directories     Create leading directories where needed
在cpio还原文件的过程中,自动的建立相应的目录。
-m, --preserve-modification-time Retain previous file modification times when creating files
在创建文件时保留以前的文件修改时间


(2)img文件压缩及解压

centos7的initrd文件解压流程:









centos6的initrd文件解压流程:









修改内核后,自定义打包一个内核initrd文件:






(3)img文件挂载方法

在linux中,对于img文件(例如,虚拟机的img文件),有时候需要将其挂载,以便修改其中的内容。能不能将它像iso文件一样挂载呢?

使用kpartx命令:

kpartx - Create device maps from partition tables
-a     Add partition mapping
-d     Delete partition mappings
-l     List partition mappings that would be added -a
-p     set device name-partition number delimiter
-f     force creation of mappings; overrides ’no_partitions’ feature
-g     force GUID partition table (GPT)
-s     sync mode. Don’t return until the partitions are created
-v     Operate verbosely


(然并卵,我在centos6和centos7失败)

据说这样使用:
kpartx -av xxx.img
mount /dev/mapper/loop0p1 /mnt


(4)模块文件:/lib/modules/VERSION-release(与内核版本发行号相同的目录)/*





arch :与平台相关的特有代码,专有的汇编级的代码

crypto:加密解密组件

drivers:驱动程序

fs :文件系统

kernel :内核自己追踪用到的文件

lib:库文件

mm:内存管理功能,memory
manage

net:网络功能

sound:和声音相关的驱动程序,单独放出来,因为有很多与声音相关的解码器

二、CentOS系列PC架构MBR主机启动流程

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

1.POST:加电自检,检查硬件设备是否存在

用于实现POST的代码在主板上ROM(CMOS)芯片上

BIOS:Basic Input and Output System 基本上输入输出系统,固化在ROM芯片上

POST(PowerOnSelfTest)首先对每一个设备进行检查。完成后会寻找存有引导记录的设备,找到后读入操作系统引导记录,然后将系统控制权交给引导记录,并由引导记录来完成系统的顺利启动。

2.Boot Sequence:

按次序查找各引导设备,第一个有引导程序的设备即为本次启动要用到的设备;





3.MBR引导,bootloader:引导加载器,程序;

MBR(Master Boot Record) MBR记录一般是在磁盘 0 磁道 1 扇区,共512个字节。前446个字节是BootLoder,后 4*16 的 64 个字节是存放分区信息的,最后 2 个字节是校验信息,一般是 55AA。

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

(1)Windows上引导加载器:ntloader

(2)Linux上引导加载器:

1)LILO:短小精悍的linux加载器,1024柱面之后无法加载,现在多用于安卓手机启动

2)GRUB:Grand Uniform Bootloader统一引导加载器

GRUB 0.X(CentOS 5/6):Grub
Legacy


GRUB 1.X(CentOS 7):Grub2,完全重写,设计理念上很大改变





GRUB(GRand Unified Bootloader)加载内核,就是MBR中的前 446 个字节,是BooTLoader的一种,它的作用是要选择要启动的内核。

1)GRUB程序的组成:

centos6:





主要是由device.map,menulst,stage1,stage2,以及一系列的stage1_5组成。对于这些部分我的理解是这样:

device.map:存放的是内核文件的根分区

menu.lis:是grub.conf的链接文件,但是这个名字我觉得更与它的功能接近,就是菜单列表。里卖弄设置了可以选择的内核菜单。存放于stage2中。

stage:用于grub引导程序过大,所以分2段引导,第一段存放在MBR中,第二段存放于内核文件系统中,第一段引导完成后可以找到
第二段。 但是,第二段是存放于内核文件系统中的,此时还没有格式化文件系统,如何可以访问到第二段的 menu.lst 呢??就需要借助于中间层
stage1_5,有它来协助 stage1 段来访问 stage2 段。stage1_5通常位于 stage1 字段后的 63 个扇区。
由于stage2 在内存中存放可以使用的文件系统不确定,所以这就是有多个 stage1_5 的原因了。

2)grub.conf 文件参数意义





default=0    # 默认启动的内核title, 0 表示是第一个
timeout=5    # 默认等待时间
splashimage=(hd0,0)/grub/splash.xpm.gz    # 指定菜单的背景图片的路径。为xpm格式,采用gzip压缩,只能为14bits色
hiddenmenu    # 隐藏菜单
title CentOS (2.6.32-431.el6.x86_64)    # 标题名,用户可自定义
root (hd0,0)    # 指定 grub 的根位置
# 指定 kernel 文件的位置,还要指出 root(系统启动后) 的位置,挂载方式 ro,这项很关键。
# 加载后会启动 init 进程。
kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=UUID=17df3f60-a2a2-4de3-bdeb-b6fb4950d848 rd_NO_LUKS  KEYBOARDTYPE=pc KEYTABLE=us
LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 rd_NO_LVM crashkernel=auto rhgb quiet rd_NO_DM rhgb quiet
# 在内核启动过程中装载根文件系统时有用
initrd /initramfs-2.6.32-431.el6.x86_64.img

# initramfs 是以 gzip 压缩的 cpio 格式的文件。内核启动时将他作为一个临时的根文件系统。 # grub 的 stage2 将initrd加载到内存里,让后将其中的内容释放到内容中,
# 内核便去执行init脚本,这时内核将控制权交给了init文件处理。
# init 它也主要是加载各种存储介质相关的设备驱动程序。当所需的驱动程序加载完后,
# 会创建一个根设备,然后将根文件系统rootfs以只读的方式挂载。
# 这一步结束后,释放未使用的内存,转换到真正的根文件系统上面去,同时运行/sbin/init程序,
# 执行系统的1号进程。此后系统的控制权就全权交给/sbin/init进程了。


Linux内核在初始化之后会执行init进程,而init进程会挂载我们的根文件系统,但由于init程序也是在根文件系统上的,所以这就有了悖论。

Linux采用两步走的方法来解决这个问题。

Linux2.6
版以前的方法是:除了内核vmlinuz之外还有一个独立的initrd.img映像文件,其实它就是一个文件系统映像,linux内核在初始化后会
mount

initrd.img作为一个临时的根文件系统,而init进程就是在initrd.img里的,然后init进程会挂载真正的根文件系统,然后
umount
initrd.img。

但Linux2.6内核的实现方式却不太一样,虽然完成的功能是一样的。Linux2.6采用initramfs。
initramfs:init ram filesystem,它是一个cpio格式的内存文件系统,制作的方法有两个,一个是http://blog.csdn.net/htttw/article/details/7215858介绍的,但这样做出来的initramfs是和内核vmlinuz分开的,因此我们需要在grub里写上initramfs的路径。

而另
一种方法是把内核和initramfs制作在一起成为一个文件,方法是在linux源码make
menuconfig,然后General setup-->选择Initial RAM filesystem and RAM disk
(initramfs/initrd) support,然后在Initramfs source
file(s)里输入我们的initramfs目录,然后make bzImage。这种方法做出来的内核就只有一个文件,不需要指定initramfs了。

从2.6内核以后真正的内核文件是initramfs开头的!!initrd开头的注意后面的结尾dump,可能是原始备份的

centos7:





3)grub的功能

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

(2)选择要启动的内核或系统

允许传递引导参数给内核

选择界面可隐藏

# 可以自启动是通过 grub 像内核传递参数。
# 应用之一是:修改 root 密码(忘记密码),使用 e 选项,传递单用户指令。


centos7:









centos6:













(3)为编辑功能提供保护机制

启用内核文件

选择运行指定的内核得先输入密码

传递参数

使用e命令得先输入密码

[root@openstack01 ~]# grub-md5-crypt
Password:
Retype password:
$1$32hfn$HcmdhoMIJvGir.2hNKz8W0
# 上面是生成的加密字符串
# 然后将信息加入到 grub.conf 文件中,格式如下:
password --md5 $1$32hfn$HcmdhoMIJvGir.2hNKz8W0
# 当然加入 grub.conf 文件的位置不同,加密效果也不一样。
# 加入到 title 之前的话,会加密整个菜单。
# 加入到 title 指内的话,会加密对应的操作系统的入口。


4.Kernel实现功能

kernel自身初始化,实现功能

---> 探测可识别到的所有硬件设备;

---> 加载硬件驱动程序;(有可能会借助于ramdisk加载驱动)

---> 以只读方式挂载根文件系统;

---> 运行用户空间的第一个应用程序:/sbin/init

5./sbin/init管理用户空间服务进程

init程序的在不同CentOS版本上类型:

CentOS 5及以前:SysV init 配置文件:/etc/inittab

CentOS 6:Ubantu研发的Upstart 配置文件:/etc/inittab /etc/init/*.conf

CentOS
7:Systemd 配置文件:/usr/lib/systemd/system/, /etc/systemd/system/

(1)CentOS 5:

SysV init,配置文件:/etc/inittab

[root@openstack01 ~]# cat  /etc/inittab
id:3:initdefault:    此处 表示默认启动级别为3文本界面,不能为0级别
/etc/inittab文件:每行定义一种action 以及与之对应的process
格式:id:runlevels:action:process
id:一个任务的标识符;
runlevels:在哪些级别启动此任务;#,###,若此处为空则表示所有级别;
action:在什么条件下启动此任务;
wait:等待切换至此任务所在的级别时执行一次;
respawn:再次发起;此任务终止,就自动重新启动;
initdefault:设定默认运行级别;此时process会省略,不是设定任务,而是默认启动级别;
sysinit:设定系统初始化方式,此处一般为指定/etc/rc.d/rc.sysinit脚本(CentOS5和6用到,7无);
process:任务;


(2)CentOS 6:
init程序:upstart,但依然为/sbin/init,
其配置文件: /etc/init/*.conf, /etc/inittab(仅用于定义默认运行级别)
注意:*.conf为upstart风格的配置文件;各功能切割成片段





init-system-dbus.conf:主要在哪儿启动服务的配置文件

rcS.conf: 系统初始化脚本

start-ttys.conf:启动时的终端数量

rc.conf:启动服务的配置文件

系统初始化首先从/etc/init/rcS.conf开始

end script
exec /etc/rc.d/rc.sysinit


rcS.conf里面有这样行,表明这个rcS.conf执行完后才开始执行rc.sysinit配置文件



更改默认tty数量文件:





(3)CentOS
7:不需要任何启动脚本

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

完全兼容SysV脚本机制;因此,service命令依然可用;不过,建议使用systemctl命令来控制服务;

#
systemctl
{start|stop|restart|status}
name[.service]

6.启动运行级别初始化控制:/etc/rc.d/rc#.d
(1)系统运行级别:为了系统的运行或维护等目的而设定的机制;
0-6:共7个级别;
0:关机, shutdown
1:单用户模式(single user),root用户,无须认证;维护模式;
2:多用户模式(multi user),会启动网络功能,但不会启动NFS;维护模式;
3:多用户模式(mutli user),完全功能模式;文本界面;
4:预留级别:目前无特别使用目的,但习惯以同3级别功能使用;
5:多用户模式(multi user), 完全功能模式,图形界面;
6:重启,reboot
1) 默认级别:3, 5
2) 级别切换:init #
3) 级别查看命令:who -r ; runlevel
(2)/etc/rc.d目录
1)rc #脚本:接受一个运行级别数字为参数;当级别切换时启动或关闭服务
K*:要停止的服务;
K##*,优先级,数字越小,越是优先关闭;依赖的服务先关闭,而后关闭被依赖的;
S*:要启动的服务;
S##*,优先级,数字越小,越是优先启动;被依赖的服务先启动,而依赖的服务后启动;
注意:按照glob通配,数字越小排在前面





注意:开机时启动的服务,越早开启,关闭的时候越靠后





2)/etc/rc.d/rc脚本框架(vim /etc/rc.d/rc)

关闭服务脚本:

for i in /etc/rc$runlevel.d/K* ; do

# Check if the subsystem is already up.
subsys=${i#/etc/rc$runlevel.d/K??}
[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] || continue
check_runlevel "$i" || continue

# Bring the subsystem down.
[ -n "$UPSTART" ] && initctl emit --quiet stopping JOB=$subsys
$i stop
[ -n "$UPSTART" ] && initctl emit --quiet stopped JOB=$subsys
done


开启服务脚本:

for i in /etc/rc$runlevel.d/S* ; do

# Check if the subsystem is already up.
subsys=${i#/etc/rc$runlevel.d/S??}
[ -f /var/lock/subsys/$subsys ] && continue
[ -f /var/lock/subsys/$subsys.init ] && continue
check_runlevel "$i" || continue

# If we're in confirmation mode, get user confirmation
if [ "$do_confirm" = "yes" ]; then
confirm $subsys
rc=$?
if [ "$rc" = "1" ]; then
continue
elif [ "$rc" = "2" ]; then
do_confirm="no"
fi
fi

update_boot_stage "$subsys"
# Bring the subsystem up.
[ -n "$UPSTART" ] && initctl emit --quiet starting JOB=$subsys
if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then
export LC_ALL=C
exec $i start
fi
$i start
[ -n "$UPSTART" ] && initctl emit --quiet started JOB=$subsys
done






开启的时候执行最后一个启动脚本时,执行/etc/rc.d/rc.local脚本,此脚本是启动过程中最后启动的一个脚本。

S99local做了一个软链接给rc.local

(3)/etc/init.d/*
(/etc/rc.d/init.d/*)脚本执行方式:

#
/etc/init.d/SRV_SCRIPT
{start|stop|restart|status}

#
service SRV_SCRIPT {start|stop|restart|status}

1.CentOS 6:

chkconfig命令:

管理控制/etc/init.d/每个服务脚本在各级别下的启动或关闭状态;

1) 查看:chkconfig --list [name]





2) 添加:chkconfig --add name

3) 删除:chkconfig --del name

4) 修改指定的链接类型:

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

--level
LEVELS:指定要控制的级别;默认为2345;

5) 能被添加的服务的脚本定义格式:

#!/bin/bash
#
# chkconfig: ###  ## ##       ======注释:运行级别、启动优先级、关闭优先级======
#
description:


2.CentOS 7:(待续)

(4)/etc/rc.d/rc.local脚本:开机自动读取此文件中命令

正常级别下,最后启动的一个服务S99local没有链接至/etc/init.d下的某脚本

而是链接至了/etc/rc.d/rc.local
(/etc/rc.local)脚本;

因此,不便或不需写为服务脚本的程序期望能开机自动运行时,直接放置于此脚本文件中即可。





7.系统初始化脚本:/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)
清理操作;

8.启动终端

tty1:2345:respawn:/usr/sbin/mingetty
tty1

...
...

tty6:2345:respawn:/usr/sbin/mingetty
tty6

(1)mingetty会调用login程序;

(2)打开虚拟终端的程序除了mingetty之外,还有诸如getty等;

启动开机流程总结:

内核级别:

1.POST做开机启动时候的硬件检测功能

2.BootSequence(BIOS)启动加载主引导分区MBR中的引导加载器程序BootLoader

在LInux现行的BootLoader是三段划分(打破446字节限制)的GRUB程序,

第1段写在BootLoader中

第1.5段在其后扇区用于文件系统的引导

第2段在boot/grub中提供国土部接口和调用系统内核kernel

3.Kernel识别硬件、加载驱动、只读挂载根文件系统、同时交付给用户空间第一个程序/sbin/init

此处特别要注意,系统发行商为了适应多种硬件接口驱动调用,会在第一次安装系统时候,自动识别硬件接口,并调用唯一驱动程序来生成ramdisk文件,以内存当磁盘做虚根,驱动接口后会切换到真实的根文件系统上

CentOS 5系列是initrd,当磁盘映像文件会造成二次缓存缓冲

CentOS 6/7系列改进为initramfs,以文件系统形式可以不二次占用缓存和缓冲

用户空间级别

4./sbin/init接管后更具其配置文件来初始化

5.根据/sbin/init中的配置会设置默认运行级别,以及一些在/etc/init.d/设置的开机服务

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

7.关闭对应级别下需要停止的服务,启动对应级别下需要开启的服务

8.设置登录终端 [--> 启动图形终端]

本文出自 “REN的博客” 博客,转载请与作者联系!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: