Linux 系统启动流程
Linux系统的组成部分:内核+根文件系统
内核
- 进程管理
- IPC Inter Process Communication
- 消息队列、semerphor、shm
- socket
- 内存管理
- 网络协议栈
- 文件系统
- 驱动程序
- 安全功能
运行中的系统环境:内核空间、用户空间
- 用户空间(用户模式):应用程序(进程或线程)
- 内核空间(内核模式):内核代码(系统调用)
IPC:Inter Process Communication
- 本地进程间通信
- 消息队列
- semerphor
- shm
- 跨主机进程间通信
- socket
分区
- 启动分区:/boot
- rootfs:FHS
内核设计
- 单内核设计:所有功能集成于同一个程序
- 代表产品:Linux
- 微内核设计:每种功能使用一个单独的子系统实现
- 代表产品:Windows, Solaris
Linux内核特点
- 支持模块化
.ko
(kernel object)除了文件系统、驱动程序等主要模块之外都使用了内核对象(模块) 是动态转载卸载的内核模块(某一种功能实现).so
(shared object,共享对象,各种应用程序之间共享的模块)
- 支持模块运行时动态装载或卸载
Linux内核组成部分:
核心文件:
/boot/vmlinuz-VERSION.release
rimdisk:虚拟内存盘
模块文件
/lib/modules/$(uname -r)/kernel/
核心文件:文件系统、驱动程序、网络协议等文件
/boot/vmlinuz-VERSION.release
- 核心文件放置文件:编译后的后文件
/boot/vmlinuz-3.10.0-327.el7.x86_64
/boot/vmlinuz-$(uname -r)
- z:内核文件压缩后文件格式
rimdisk:虚拟内存盘
- 虚拟内存盘是通过软件将一部分内存(RAM)模拟为硬盘来使用的一种技术。相对于直接的硬盘文件访问来说,这种技术可以极大的提高在其上进行的文件访问的速度。但是RAM的易失性也意味着当关闭电源后这部分数据将会丢失。但是在一般情况下,传递到RAM盘上的数据都是在硬盘或别处永久贮存的文件的一个拷贝。经由适当的配置,可以实现当系统重启后重新建立虚拟盘。
- CentOS 5: /boot/initrd-VERSION-release.img
- rd:(ram disk)内存当磁盘使用,磁盘里必须有缓存和缓冲)
- CentOS 6,7: /boot/initramfs-VERSION-release.img
- ramfs:文件系统,避免双缓存缓冲,提高性能速度
Linux 模块文件
/lib/modules/$(uname -r)/kernel/
- arch 平台相关的特有代码(汇编级别)
- fs 文件系统,ext2,ext3编译进内核中
- drives 驱动程序
- crypto 加密/解密组件模块
- lib 库
- mm 内存功能
- net 网络功能
- sound 声音相关驱动程序,解码器
- kernel 内核追中到的文件模块
Linux 内核版本
mainline:正在研发主板版本
stable: 稳定版,不增加功能,只要负责修复bug
longterm: 长期维护版
linux-next
CentOS 6: 2.6.X
CentOS
7
,MNBVCXZAhj
`: 3.10.X
内核启动之后,加载根文件系统,然后运行init进程,init进程用户所有进程,内核退回只在特权指令时运行
CentOS 系统的启动流程
1. POST(Power On Self 加电自检,检查内存,磁盘,显示等硬件是否存在)
- ROM: CMOD(主板上的识别设备只读程序)
- BIOS: Basic Input and Output System,基本输入输出系统
- ROM + RAM: 只读内存+随机内存
2. Boot Sequence: 引导过程
按次序查找各引导设备,第一个有引导程序的设备即为本次启动要用到的设备
bootloader:引导加载器,程序
- Windows:ntloader
- Linux:
- LILO: LInux LOader(手机设备)
- GRUB: Grand Uniform Bootloader,同一引导加载器
- GRUB 0.x(Grub Legacy): CentOS 5,6
- GRUB 1.x: (Grub2,完全重写) CentOS 7
- 功能:提供一个菜单,允许用户选择要启动的系统或不同的内核版本;把用户的选定的内核装载到RAM中的特定空间中,解压、展开,而后把系统控制移交给内核;
MBR:Master Boot Record, 512bytes
- 446bytes: bootloader
- 64bytes: fat filesystem all table
- 2bytes: 55AA(有效MBR)
注意:UEFI, GPT
- GRUB: 两个阶段
- Bootloader: 1st stage
- Partition: filesystem diver 1.5 stage
- Partition: /boot/grub, 2nd stage
3. Kernel
自身初始化
- 探测可识别到的所有硬件设备
- 加载硬件驱动程序(有可能借助于ramdisk加载驱动)
- 以只读方式挂载根文件系统
- 运行用户空间的第一个应用程序:/sbin/init
init程序类型:
CentOS 5>:SysV init
- 配置文件:/etc/inittab
CentOS 6: Upstart(基于Ubuntu)
- 配置文件:/etc/initab(废弃), /etc/init/*.conf
CentOS 7: Systemd
- 配置文件:/usr/lib/systemd/system/, /etc/systemd/system/
ramdisk
Linux内核的特性之一:使用缓冲和缓存来加速对磁盘上的文件访问
ramdisk --> 内存当磁盘使用
ramdisk --> ramfs 提速机制
CentOS 5: initrd
- 工具程序:
mkinitrd
- 工具程序:
CentOs 6,7: initramfs
- 工具程序:
dracut,mkinitrd
- 工具程序:
系统初始化流程(内核级别)
- POST
- BootSequence(BIOS)
- Bootloader(MBR)
- Kernel(ramdisk)
- rootfs(read only,避免BUG),自动挂载根文件系统
- switchroot
- 运行用户空间的/sbin/init程序
- (/etc/inittab, /etc/init/*.conf)
- 设定默认运行界别
- 系统初始化脚本
- 关闭或启动对应界别下的服务
- 启动终端
注意:Bootleader不能加载软设备上 内核文件必须放在基本磁盘设备上(不能放在LVM等设备上)
/sbin/init
- CentOS 5: Sysv init
运行级别:为了系统的运行或维护的目的而设定的机制
0: 关机模式,shutdown
1: 单用户模式(single user),root用户,无需认证;维护模式
2:多用户模式(multi user),有认证机制,会启动网络功能,但不会启动NFS;维护模式
3:多用户模式(multi user),完全功能模式;文本界面
4:预留级别,目前无特别适用目的,当习惯一同3级别功能使用
5:多用户模式(multi user),完全功能模式;同行界面
6:重启模式,reboot
默认级别:
- 3: 服务器
- 5: 个人级别
界别切换命令
# init [0-6]
级别查看
# who -r
# runlevel
- N 3:
- N: 上一个级别 3:当前级别
- N:表示没有上一个级别
配置文件:/etc/inittab
每行定义一种
action
以及与之对应的process
(CentOS 5)
id:runlevels:action:process
- id:一个任务的标识符
- runlevels:在哪些级别启动此任务;
# or ###
,也可以为空,表示所有级别 - action: 在什么条件下启动此任务
- process: 任务(应用程序或脚本)
action
- wait: 等待切换至此任务所在的级别时执行一次(刚刚切换时执行一次)
- respawn: 一旦此任务终止时,就自动重新启动之, Login -> login ->login(提示)
- initdefault: 设定默认运行级别;此时,process省略
- sysinit: 设定
系统初始化方式
,此处一般为指定/etc/rc.d/rc.sysinit
脚本(CentOS 5,6)
例如
id:3:initdefault
si::sysinit:/etc/rc.d/rc.sysinit 系统初始化
l0:0:wait:/etc/rc.d/rc 0 切换至0级别时执行/etc/rc.d/rc 参数为0
rc脚本:接受一个运行界别数字为参数
l0:1:wait:/etc/rc.d/rc 1
l0:2:wait:/etc/rc.d/rc 2
l0:3:wait:/etc/rc.d/rc 3
l0:4:wait:/etc/rc.d/rc 4
l0:5:wait:/etc/rc.d/rc 5
l0:6:wait:/etc/rc.d/rc 6
lo:0:wait:/etc/rc.d/rc 3
意味着启动或关闭 /etc/rc.d/rc3.d/
目录下的服务脚本所控制服务
K*
:要停止的服务K##*
:优先级,数字越小, 越优先关闭- 依赖的的服务先关闭,而后关闭被依赖的
S*
:要启动的服务S##*
:优先级,数字越小,越是优先启动- 被依赖的服务先启动,而依赖的服务后启动
rc 脚本
:接受一个运行界别数字为参数
脚本框架
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
/etc/init.d/* (/etc/rc.d/init.d/*)
脚本执行方式
# /etc/init.d/SRV_SCRIPT {start|stop|restart|status}
/etc/init.d = /etc/rc.d/init.d
# /etc/initd./crond {start|stop|restart|status}
# service SRV_SCRIPT {start|stop|restart|status}
chkconfig 命令
创建
K*,S*
文件
管控/etc/init.d/
每个服务脚本在各个级别下的启动或关闭状态
查看
# chkconfig --list [SERVICE_NAME]
添加
# chkconfig --add SERVICE_NAME`
能被添加的服务的脚本定义格式之一
#!/bin/bash
# chkcofig: 2323 START_nice STOP_nice
# description: content
删除
# chkconfig --del SERVICE_NAME
修改指定的链接类型
#chkconfig [--level LEVELS] name <on|off|reseat>
--level LEVELS:指定要控制的级别;默认为2345
启动级别
- 启动优先级:小于所有依赖于此服务的其他服务的优先级(因为他被依赖,先启动)
- 关闭优先级:大于所有依赖于此服务的其他服务的优先级(因为他被依赖,后关闭)
# vim /etc/init.d/testsrv
#!bin/bash
# testsrv This starts and stops testsrv
#
# chkconfig: 2345 11 88 - 11 99 任何级别都没有
# description: This test service
# `
prog=$(basename $0)
if [ $# -lt 1 ]; then
echo "User:$prog {start|stop|status|restart}"
exit 1
fi
if [ "$1" == "start" ]; then
echo "Start $prog finished."
elif [ "$1" == "stop" ]; then
echo "Stop $prog finished."
elif [ "$1" == "restart" ]; then
echo "Restart $prog finished."
elif [ "$1" == "status" ]; then
if pidof $prog &> /dev/null; then
echo "$prog is running"
else
echo "$prog is stopped."
fi
else
echo "Usage: $prog {start|stop|status|restart}";
exit 2
fi
# chmod +x testsrv
# bash -n testsrv
# chkconfig --add testsrv 初始化testsrv服务
# chkconfig testsrv on
# ls /etc/rc.d/rc3.d/ | grep testsrv
# chkconfig --del testsrv
# chkconfig --level 0123456 testsrv off
# chkconfig --level 35 testsrv on
注意: 正常级别下,最后启动的一个服务S99local没有链接至/etc/init.d下的某脚本,而是链接至了/etc/rc.d/rc.local脚本;因此,不便或不需要为脚本的程序期望能开机自动运行时,直接放置于此脚本文件中即可。
/etc/rc.d/rc3.d/S99local => /etc/rc.d/rc.local
/etc/rc.local => /etc/rc.d/rc.local
tty1:2345:respawn:/usr/sbin/mingetty tty1
tty6:2345:respawn:/usr/sbin/mingetty tty6
- mingetty调用login程序
- 打开虚拟终端的程序除了mingetty之外,还有诸如gettty等
tty7:5:respawn:/etc/X11/
CentOS 5 系统初始化脚本
/etc/rc.d/rc.sysinit
- 设置主机名
/bin/hostname, /etc/sysconfig/network
- 设置欢迎信息
- 激活
udev
和selinux
- 挂载
/etc/fstab
文件中定义的所有文件系统 - 检测根文件系统,并以读写方式挂载根文件系统
- 设置系统时钟
- 根据
/etc/sysctl.conf
文件的设置内核参数 - 激活
vim
及软raid设备
- 激活
swap设备
- 加载额外设备的驱动程序
- 清理操作
用户空间的启动流程:/sbin/init(/etc/inittab)
- 设置默认运行级别
- 运行系统初始化脚本,完成系统初始化
- 关闭对应级别下要停止的服务,启动对应级别下需要开启的服务
- 设置登录终端
- 启动图形终端
### CentOS 6
- init程序:
upstart
,但依然为/sbin/init
,其配置文件:/etc/init/*.conf, /etc/inittab
(仅用于定义默认运行级别)- 注意:
*.conf
为upstart风格的配置文件rcS.conf
初始化脚本rc.conf
服务开发关闭脚本start-ttys.conf
启动终端服务脚本
CentOS 7
- init程序:
systemd
- 配置文件:
/usr/lib/systemd/system/*, /etc/systemd/system/*
- 完全兼容Sysv脚本机制;service命令依然可以使用;建议使用systemctl命令来控制服务
- 配置文件:
# systemctl {start|stop|restart|status} name[.service]
# systemctl get-default
multi-user.target
启动为什么快?
所有服务都没有启动。当第一次启动的时候启动服务
博客作业:UEFI,GPT;CentOS启动流程
CentOS 6启动流程
- POST
- Boot Sequence(BIOS)
- Boot Loader(MBR)
- Kernel(ramdisk)
- rootfs
- switchroot
- /sbin/init
- (/etc/inittab, /etc/init/*.conf)
- 设定默认运行界别
- 系统初始化脚本
- 关闭或启动对应级别下的服务
- 启动终端并显示登录提示符
## GRUB(Boot Loader)
grub: Grand Unified Bootloader
- Grub 0.x: grub legacy
- Grub 1.x: grub2
Grub legacy
Stage1: mbr
Stage1_5: mbr之间的扇区,让stage1中的boot loader能识别stage2所在的分区上的文件系统
Stage2: 磁盘分区(/boot/grub/)
配置文件:
/boot/grub/grub.conf <-- /etc/grub.conf
Stage2 及内核等通常放置于一个基本磁盘分区
- 功用:
- 提供菜单,并提供交互式接口
e: 编辑模式,用于编辑菜单
c: 命令模式,交互式接口
- 加载用户选择的内核或操作系统
允许传递参数给内核
可隐藏此菜单
- 为菜单提供了保护机制
- 为编辑菜单进行认证
- 为启动内核或操作系统进行认证
grub 如何识别设备
hd#, #
(hd:hardware,#:第几块磁盘,第几个分区)- hd#:磁盘编号,用数字表示;从0开始编号
- #:分区编号,用数字表示;从0开始编号
- (hd0,0)
grub 的命令行接口
help:获取帮助列表
help root:设置grub的根设备
help KEYWORD:详细帮助信息
find (hd#,#)/PATH/TO/SOMEFILE
find (hd0,0)/wmlinuz- tab键
root (hd#,#) 设定哪个设备的哪个分区作为根文件系统
root (hd0,0)
find /vmlinuz-2.6.32-504.e.....
kernel /PATH/TOKERNEL_FILE:本次启动时用到内核文件(z代表压缩文件);额外还可以添加许多内核支持使用的cmdline参数:
例如:`init=/path/to/init, selinux=0`
initrd /PATH/TO/INITRAMFS_FILE:设定为选定的内核提供额外文件的ramdisk
boot:引导启动选定的内核
手动在 grub 命令行接口启动系统
grub> root(hd0,0) 选择根文件系统
grub> kernel /vmlinuz-VERSION-RELEASE ro root=/dev/mapper/vg0-root quite 启动内核文件,只读,选择根文件系统设备,静默模式(初始化显示信息不现实)
grub> initrd /initramfs-VERSION-RELEASE.gim 默认启动程序
grub> boot
grub2 命令行接口
help 显示所有可用命令
ls 列出当前的所有设备
ls -l 列出当前的所有设备,对于分区显示其label及uuid
ls (hd1,1) 列出(hd1,1)分区下文件
search -f /ntldr 列出根目录里包含ntldr文件的分区,返回为分区号
search -l Linux 搜索label是linux的分区
search --set -f /ntldr 搜索根目录包含ntldr文件的分区并设为root,注意如果多外分区含有ntldr文件,set失去作用
set root= 设置变量的值
set timeout= 设置变量的值
调用变量的值时,使用${AA},如set root=(hd1,1),则${root}=(hd1,1)
linux取代grub中的kernel
boot
GRUB 配置文件:/boot/grub/grub.conf
default=0 设定默认启动的菜单项;菜单项(title)编号从0开始
timeout=5 指定菜单项等待选项选择的时长
splashimage=(hd0,0)/grub/xpm.gz 菜单背景图片文件路径(14位图像600x800)
hiddenmenu 隐藏菜单
password [--md5] STRING:菜单编辑认证
- Password --md5 $1$TOrM8/$zY5p2Lr4CbXBqXyfguLaG.
title TITLE : 定义菜单项的标题,可出现多次
- root (hd#,#):grub查找stage2及kernel文件所在设备分区;为grub的根
- kernel /PATH/TO/vmlinuz_FILE [PARAMETERS] 启动的内核
- initrd /PATH/TO/INITRAMFS_FILE : 内核匹配的
ramfs
文件 - password [--md5] STRING:启动选定的内核或操作系统时进行认证
# grub-md5-crypt
:生成grub密码复制到 "STRING" 位置# openssl
生成密码串
如何进入单用户模式?
- 编辑 grub 菜单(选定要编辑的title,而后使用e命令)
- 在选定的kernel后附加; 1,s,S或single都可以
- 在 kernel 所在上,键入"b"命令
安装 grub 方法(2种)
1. 第一步
# grub-install --root-directory=ROOT /dev/DISK
2. grub 修复
# grub> root (hd#,#) stage1,stage1.5必须存在
# grub> setup (hd#)
创建系统
添加一个硬盘sdb
- 创建分区:boot(100Mb), root(5G),swap(1G)
- 创建文件系统:ext4,ext4
- 挂载文件:
# mkdir /mnt/boot
# mount /dev/sdb1 /mnt/boot/
# ls /mnt/boot
# grub-install --root-directory=/mnt /dev/sdb
# ls -l /mnt/boot/grub/
没有grub配置文件,需要自己配置
# vim /mnt/boot/grub/grub.conf
default=0
timeout=5
titie Centos(Expres)
root (hd0,0)
kernel /vmlinuz ro root=/dev/sda3 selinux=0 init=/bin/bash
initrd /initramfs.img
没有kernel文件,需要复制
# cp /boot/vmlinuz-ss /mnt/boot/vmlinuz
没有initramfs文件,需要复制
# cp /boot/initramfs-.. /mnt/boot/initramfs.img
创建系统目录
# mkdir /mnt/sysroot
# mount /dev/sdb3 /mnt/sysroot/
# cd /mnt/sysroot/
# mkdir -pv etc bin sbin lib lib64 dev proc sys tmp var usr home root mnt media
# cp /bin/bash /mnt/sysroot/bin/
# ldd /bin/bash` 查看bash依赖哪些库文件
# cp /li64/libtiinfo.so.5 /mnt/sysroot/lib64/
......
# chroot /mnt/sysroot/ 切换根文件系统
# sync 同步
创建虚拟机刚才创建生成的新的系统磁盘
...
grub菜单文件丢失怎么办?
grub文件丢失,说明bootloader丢失
修复MBR,硬盘接到其他机器上,修复MBR的bootloader程序
# dd if=/dev/sda of=/root/mbr.bak count=1 bs=512
# dd if=/dev/zero of=/dev/sda bs=200 count=1
# sync 同步到磁盘上
# grub-install --root-directory=/ /dev/sda boot所在的根目录
# sync
# dd if=/dev/zero of=/dev/sda bs=200 cont=1
# grub
grub> root (hd0,0)
grub> setup (hd0) hd0硬盘
grub> exit
# sync
# reboot
紧急求援模式
# dd if=/dev/zero of=/dev/sda bs=200 cont=1
# sync
# reboot
- 载入光盘设备:
- 选择 Rescure installed system
- 输入 boot: linux rescure
# chroot /mnt/sysimage/
# grub-install --root-directory=/ /dev/sda
# reboot
练习
- 新加硬盘,提供直接单独运行bash系统
- 破坏本机grub stage1, 而后在救援模式下修复之
- 为grub设备保护功能
ldd命令
应用程序命令所依赖的库文件
# ldd /PATH/TO/COMMAND
- 库文件名 => 库文件路径
linux-vdso.so.1 => (0x00008fffea5a3000)
系统调用库入口/lib64/ld-linux-x86-64.so.2
各应用程序调用其他库文件入口
# ldd /bin/ls | grep -o "/lib[^[:space:]*"