要想维护好linux,首先需要掌握linux的启动流程,看起来黑屏白字忽闪忽闪启动就启动了,但你真的知道操作系统在后台都做了些什么吗,如果系统启动过程中报错起不来了,你知道是哪个步骤出错了吗,你知道如何去修复吗,这就需要我们对linux启动过程做一个详尽的了解,以帮助我们更好更快的去排错以及修复。今天就给大家分享这一话题。


一、Centos系统启动流程简介:

POST(加电自检)——>Boot sequence(BIOS)——>Bootloader(MBR)——>kernel(ramfs)——>Rootfs(readonly)——>switchroot(readwrite)——>/sbin/init——>设定默认运行级别——>系统初始化——>启动和停用对应级别下的服务——>启动终端[——>启动图形界面]


1,linux系统的组成部分:内核+根文件系统

2,内核功能:进程管理、内存管理、网络协议栈、文件系统驱动程序、安全功能


IPC:Inter Process Commuication 进程间通信

   semerphor、shm 消息列队


3,运行中的系统环境可分为两层:内核空间、用户空间

内核空间:内核代码(系统调用)

用户空间:应用程序(进程或线程)


4,内核设计流派:

单内核设计:把所有的功能集成在同一个程序中

linux

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

windows,solaris


5,linux内核特点:

(1)支持模块化(linux系统中的.ko文件,kernel object)

(2)支持运行过程中模块的动态装载与卸载


6,linux内核组成部分:

核心文件:/boot/vmlinuz-version-release(linuz:z意为压缩文件)

模块文件:/lib/modules/version-release


7,ramdisk:内存磁盘

Centos 5:/boot/initrd-version-release.img

Centos 6 7:/boot/initramfs-version-release.img


initrd(initramdisk)——>initramfs

如果使用ramdisk逻辑,既然是当作磁盘设备,与系统交换时就需要创建缓冲(buffer)与缓存(cache)

制作工具:mkinitrd

如果使用ramfs逻辑,就不需要buffer与cache,能够节省资源

制作工具:mkinitrd、drwcut


(一)内核级别的启动流程:

POST(加电自检)——>Boot sequence(BIOS)——>Bootloader(MBR)——>kernel(ramfs)——>Rootfs(readonly)——>switchroot(readwrite)


1,POST:加电自检

检查系统运行需要的基本硬件有无错误或缺失,这些自检工作是由固化在CMOS中BIOS程序来实现的,检测硬件正常后进行硬件设备的初始化


2,Boot sequence:按次序检查各引导设备,第一个有引导程序(bootloader)的设备,即为本次启动设备,找到启动设备后,开始读取设备中操作系统的核心文件,由于操作系统的不同,文件系统的格式也不同,为了避免出现不兼容的问题,就需要一个启动管理器来统一管理这些核心文件,这个启动管理器也就是bootloader


bootloader功能:

识别、加载操作系统的核心文件,并提交内核运行,进而启动操作系统

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


bootloader:引导加载器

windows系统:ntloader

linux系统:

LILI:LInux LOader  1024柱面之后无法加载,现在多用于安卓手机启动

Grub:Grand uniform bootloader

Grub 0.x:Grub Legacy

Grub 1.x:Grub2  代码完全重写,设计理念上改变很大

如果要想让windows系统和Linux系统共存,最好先安装windows,再安装linux,如果先安装linux,再安装windows,windows会把linux系统的bootloader覆盖掉,而linux的bootloader却可以在读取bootloader之后把启动管理功能移交给windows,从而可以继续启动windows系统,但windows的bootloader做不到。


MBR:Master Boot Record

0磁道0扇区的512字节

前446字节:bootloader引导加载器

后64字节:FAT文件系统配置表

最后2字节:活动分区标签


Grub:bootloader的实现工具

1st stage:bootloader主程序,存放在MBR中,Boot sequence可以直接读出来

1_5 stage:文件系统驱动,存放MBR之后到2047扇区中,存放stage2所在分区(也即boot分区或者根分区)的文件系统驱动程序

2nd stage:存放在/boot/grub目录中,通过bootloader加载所有配置文件及相关环境参数信息


3,kernel:加载系统内核,执行系统信息初始化。在bootloader开始读取操作系统内核文件之后,接下来就把内核文件解压并装载到内存当中去,然后根据内核提供的功能开始检测与加载各种设备,此时,内核程序已经完全接管了BIOS的工作,之后的操作都是由内核来完成的。内核文件通常放置在/boot目录中,并且是一个以vmlinuz-version-release命名的文件。问题来了,此时内核程序还没有装载文件系统,又怎么能够找到根下的boot目录了,为了解决这一问题,操作系统引入了虚拟文件系统这一概念,也就是RAMFS(早期系统中称为RAMDISK),而这个RAMFS是存放在/boot目录下以initramfs-version-release命名的一个文件(早期系统以initrd开头),好在RAMFS文件能够通过bootloader程序将其加载到内存中,然后这个文件会被解压缩并在内存中模拟一个根文件系统,这个根文件系统能够提供一个可以运行的程序,通过该程序可以加载在启动过程中需要装载的核心模块,如RAID、LVM、SCSI等高级文件系统与驱动程序,加载完成之后,会协助内核调用/sbin/init来执行后续启动。


自身初始化

探测可识别的所有硬件设备

加载硬件驱动,有可能借助于ramfs加载驱动

以只读方式挂载系统真实根文件系统

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


4,boot目录:

(1)如果boot目录单独分区必须是标准分区,不能划分在软件RAID或LVM上,因为bootloader446字节空间有限,无法加载RAID或LVM这些高级文件系统的驱动,同时Kernel也是存放在boot分区上的,如果boo分区无法识别,也就会导致kernel是无法加载,系统想运行起来根本无从谈起

(2)如果根文件系统不使用软RAID、LVM、btrfs等高级文件系统,boot目录不以不用单独分区


(二)用户级别的启动流程:

/sbin/init——>设定默认运行级别——>运行系统初始化脚本(/etc/rc.d/rc.sysinit)——>启动和停用对应级别下的服务——>启动终端[——>启动图形界面]


1,init程序的类型:

Centos 5:SysV init

配置文件:/etc/inittab

Centos 6:Upstart

配置文件:/etc/inittab、/etcinit/*.conf

Centos 7:systemd

配置文件:/etc/systemd/system、/usr/lib/systemd/system


2,/sbin/init

Centos 5:SysV init

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

0-6:7个级别

0:关机,shutdown

1:单用户模式(single user),此模式下root用户无须认识,属维护模式

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

3:多用户模式(mutil user),完全功能模式(正常模式),字符界面

4:预留级别:目前无特别使用目的,但习惯

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

6:重启,reboot


默认级别:3,5

级别切换:init #

查看运行级别:runlevel 或 who -r


3,系统初始化脚本(/etc/rc.d/rc.sysinit):

(1)设置系统时钟

(2)设置主机名

(3)设置欢迎信息

(4)激活udev和selinux

(5)加载额外设备的驱动程序

(6)激活软件RAID和LVM设备

(7)挂载/etc/fstab文件中定义的所有文件系统(包括swap分区)

(8)检测根文件系统,并以读写方式重新挂载根文件系统

(9)根据/etc/sysctl.conf文件来设置内核参数

(10)清理系统系统过程中产生的垃圾文件


4,配置文件:/etc/inittab

每次运行一种action以及与之对应的process(Centos5系统)

ID:runlevels:action:process

id:一个任务的标识符

runlevel:在哪些级别下启动此服务

#,###,也可以为空,表示所有级别

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

process:任务

action:

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

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

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

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


/etc/rc.d/rc#.d目录下的脚本控制的就是系统的服务

k*:要停止的服务,k##*优先级,数字越小,越先关闭,先关闭依赖的服务,再关闭被依赖的

s*:要启动的服务,s##*优先级,数字越小,越先启动,先启动被依赖的服务,再启动依赖的


注意:按照glob通配规则,数字越小排序越靠前,所以越先被执行


5,服务脚本的框架:

for srv in /etc/rc.d/rc#.d/k*;do

$srv stop

done


for srv in /etc/rc.d/rc#.d/s*;do

$srv start

done


6,服务脚本的执行方式:

(1)/etc/init.d/script_name {start|stop|restart|status}

(2)service script_name {start|stop|restart|status}


7,Centos7上的服务使用瞬态(Transient)服务思想被xinetd进程所管理

进入的请求首先被xinetd代理

配置文件:/etc/xinetd.conf、/etc/xinetd.d/srv_name

与libwrap.so文件链接

用chkconfig控制的服务:chkconfig tftp on


8,chkconfig命令:管控/etc/init.d目录下的所有服务的启动关闭

chkconfig --list [script_name]查看所有级别下服务的运行状态

chkconfig --add [script_name]把标准格式的脚本添加进服务

chkconfig --del [script_name]删除服务

chkconfig 生效级别 [script_name] {on|off|reset}修改服务


9,服务脚本的标准文件头:

#!/bin/bash

#description:

#chkconfig 生效级别 启动序号 关闭序号


注意:正常级别(3,5)最后启动的一个服务s99local没有链接到/etc/init.d目录下的某个脚本,而是链接到了/etc/rc.d/rc.locl(/etc/rc.local)脚本,因此不便写成脚本或者不方便写成脚本的程序希望开机自启动的,可以直接写入些脚本中


10,inittab文件中有几行tty,就可以打开几个终端(默认6个)

tty#:生效级别:respawn:/usr/sbin/mingetty tty#

(1)mingetty调用login程序实现用户登录验证

(2)打开虚拟终端的程序除了mingetty,还有getty


11,Centos 6 init程序

upstart风格,根本就不是原来init程序了,但依然命名为/sbin/init

upstart配置文件:/etc/init/*.conf,/etc/inittab

仅用于定义默认运行级别

rcs.conf:系统初始化脚本

rc.conf:服务启动脚本

start—tty.conf:终端启动脚本


12,Centos 7 init程序

systemd风格,完全兼容SysV风格和Upstart风格

systemd配置文件:/etc/systemd/system/*,/usr/lib/systemd/system/*(大多为.service脚本)

service命令依然可用,但建议使用systemctl控制服务

systemctl命令用法:

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


13,grub(bootloader)

grub legacy:

stage1:mbr中的bootloader

stage1_5:mbr之后的扇区的数据

让state1中的bootloader能识别stage2所在分区的文件系统(否则没办法加载stage2)

stage2:磁盘分区(boot/grub),state2及内核文件等通常放置于一个单独的基本分区上


grub配置文件:/boot/grub/grub.conf(是/etc/grub.conf链接的源文件)


14,grub功能:

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

a:修改内核参数

e:编辑模式,用于编辑grub.conf文中的菜单内容

c:命令模式,grub交互式接口

在这里所做的修改生效于本次启动

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

允许用户传递参数给内核

可以隐藏选择菜单

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

为编辑菜单进行口令认证

为启动内核或操作系统进行口令认证


15,grub命令模式的使用:

help:获取帮助列表

help keyword获取指定命令的详细帮助信息

root (hd0,0)

find (hd0,0)或/(需是提前设定过root的) /part/to/filename

kernel /path/to/kernel_file设定本次启动时用到的内核文件 init=/path/to/init设定用户级别运行的第一个应用程序 root=/dev/sd## 系统启动后根分区所在位置 selinux=0禁用selinux模块

initrd /path/to/initramfs_file设定为选定的内核提供的boot分区或目录的内存文件系统的驱动


16,boot分区在被RAMFS挂载的过程中会被直接看作整个文件系统的根,所以在gurb中会被直接表示为root(hd0,0)第一块硬盘的第一个分区

所有boot分区下vmlinuz文件路径可以直接表示为/vmlinuz


17,手动输入grub启动信息:

grub>root (hd0,0)

grub>kernel /vmlinuz-version-release ro root=/dev/device

grub>initrd /initramfs-version-release.img

grub>boot


18,grub.conf(/boot/grub/grub.conf)文件的格式:

default=#设定默认启动的菜单选项,编号从0开始

timeoute=#指定菜单等待用户选择的时长

splashp_w_picpath=(hd0,0)/path/to/xpm-pic-file设定菜单选择界面的背景图片

hiddenmenu隐藏菜单

password [-md5] string设定菜单编辑口令

title TITLE设定菜单名称 可以重复多次(也就是说可以有多个菜单)

password [-md5] STRING设定操作系统或内核启动口令

root (hd#,#)指定grub根文件系统的位置(boot分区的位置)

kernel /path/to/vmlinuz_file内核文件的路径

initramfs /path/to/initramfs_file boot目录或分区的文件系统驱动程序的路径


grub菜单密码生成工具:gub-md5-crypt


19,grub两种重装方式:

(1)grub-install grub目录下可以没有任何文件

grub-install --root-directory=ROOT /dev/sd#(注意:不是分区)

grub-install 重装的是stage1


(2)grub grub目录下的所有文件必须都存在

grub>root (hd#,#)

grub>setup hd#

grub>setup 重装的是stage1_5(MBR之后的27扇区的数据)


20,进入单用户模式:

(1)编辑grub菜单(选定要编辑的title,使用e命令进入编辑状态)

(2)在选定的kernel后面添加参数1,s.S,single

(3)确认后返回kernel行使用b命令启动


21,kernel的组成部分:

内核核心:一般为bzp_w_picpath,通常位于/boot目录

vmlinuz-version-release


内核对象:kernel object即为内核模块

一般放置于/lib/modules/version-release

内核模块与内核核心版本一定要严格匹配


ramfs(ramdisk):辅助性文件,并非必须,如果所有的代码全部编译进内核,不采用模块加载,就用不到ramfs

目标设备驱动:SCSI

逻辑设备驱动:LVM

文件系统驱动:xfs


ramfs是一个简装版的根文件系统,位于内存中,由于使用ramfs无法持久存放数据,所以在装载ramfs启动完系统后就必须执行一个切根操作,操作系统的数据转移到一个持久存储设备上


22,相关命令:

uname:显示系统信息

-r 显示系统内核版本

-n 显示主机名

-a 显示所有系统信息


lsmod:获取内核装载模块信息

等同于:cat /proc/modules


modinfor:显示内核模块的信息

-F module_name 显示指定模块的信息

-n 显示模块文件路径


modprobe:动态装载或卸载模块

moudule_name 动态装载模块

-r module_name 动态卸载模块


depmod:动态为内核模块生成依赖关系


模块装载与卸载的另一级命令(无法解决模块依赖关系)

insmod module_filename 装载模块

rmmod module_name卸载模块


23,ramfs文件的管理

(1)mkinitrd 为当前使用中的内核重新生成ramfs文件

mkinitrd [option] initramfs-p_w_picpath kernel-version

--with=module_name 封装除默认模块之外的模块到initramfs文件中

--preload=module_name 指定initramfs文件中需要预先装载的模块

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


(2)dracut 功能比mkinitrd更底层,实用于Centos6以上的版本中

dracut [option] initramfs-p_w_picpath kernel-version

dracut /boot/initramfs-$(nuame -r).img $(uname -r)


24,内核信息输出的伪文件系统:

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

参数:只读:信息输出 如/proc/#/*

     可写:可授受用指定的值来配置内核功能特性

/proc/sys:net/ipv4/ip-forward相当于net.ipv4.ip_forward

内核参数的查看与修改:

(1)sysctl -a 查看/proc/sys目录下所有内核参数的值

sysctl variable(选项名称)查看指定参数的值

sysctl -w variable=value 修改指定参数的值


(2)cat,echo 操作内核参数

cat /proc/sys/path/to/some-kernel-file查看指定内核参数的值

echo “value” > /proc/sys/path/to/some-kernel-file 修改参数值


注意:这两种方式修改的参数值都是临时生效(重启后就失效)


(3)长期生效写入配置文件:/etc/sysctl.conf

 /etc/sysctl.d/*.conf(Centos7系统)

配置文件立即生效方式:sysctl -p


常用内核参数:

net.ipv4.ip_forward核心转发功能(路由功能)

net.ipv4.icmp_echo_ignore_all忽略所有其它主机的ping操作

kernel.hostname主机名

vm.drop_caches回收buffer与cache使用的内存空间


/sys目录

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

udev:通过读取/sys目录下的硬件设备信息,按需生成各硬件设备的设备文件

udev是用户空间程序

管理工具:devadmin 设备管理

 hotplug热插拔设备管理


udev为设备创建设备文件时会读取预先定义好的规则文件

udev规则文件:/etc/udev/rules.d/*

 /etc/lib/udev/rules.d/*


克隆虚拟机后更新网卡MAC地址不需要重启的方法:

(1)清除/etc/udev/rules.d/70-presistent-net.rules文件内容

(2)卸载网卡模块 modprobe -r e1000

(3)重新装载网卡模块:modprobe e1000


二、CentOS系统启动流程总结:

1.加载BIOS的硬件信息,获取第一个启动设备

2.读取第一个启动设备MBR的引导加载程序(grub)的启动信息

3.加载操作系统的内核文件kernel,核心开始解压缩,并尝试驱动所有的硬件设备

4.核心执行init程序,并获取默认的运行环境

5.init程序执行/etc/rc.d/rc.sysinit文件

6.检查文件系统,并以读写方式挂载真实根文件系统

7.启动核心的外挂模块

8.init执行运行的各个批处理文件(scripts)

9.init执行最后一个脚本/etc/rc.d/rc.local

10.执行/bin/login程序,等待用户登录