1. Linux启动流程
POST --> Boot Sequence --> bootloader(MBR) --> Kernel --> 加载rootfs --> switchroot --> /sbin/init --> (配置文件:/etc/inittab, /etc/init/*.conf) --> 根据init配置文件设置默认运行级别 --> 运行系统初始化脚本/etc/rc.d/rc.sysinit,完成系统初始化 --> 开启或关闭用户选定的对应运行级别下所对应的服务 --> 启动终端,打印登录提示符
- POST:检测各个硬件设备是否存在而且能够正常运行起来,实现这一自检功能的是主板上
CMOS芯片上的BIOS,主要机器一通电,CPU就会自动加载该系统,从而实现硬件的初始化. 
- POST:检测各个硬件设备是否存在而且能够正常运行起来,实现这一自检功能的是主板上
 - Boot Sequence:选择要启动的硬件设备以加载MBR,然后读取该设备MBR里的
bootloader,该顺序可以在BIOS中的boot选项卡中设置. 
- Boot Sequence:选择要启动的硬件设备以加载MBR,然后读取该设备MBR里的
 bootloader(MBR):提供一个可视化菜单给用户,让用户去选择要启动的系统或不同的系统内核版本,然后把用户选择的内核版本加载至RAM中的特定空间,接着在RAM中解压、展开,而后把系统控制权移交给内核.
grub是bootloader中的一种,此外还有LILO,此处将对grub进行说明grub 0.x又称为grub legacy,而grub 1.x被称为grub2.为了打破MBR中只有446Bytes用于存放bootloader这一限制,grub是通过三个阶段来实现加载内核的.
stage1:存放于MBR的前446Bytes,用于加载stage1.5阶段,目的是为了识别并驱动stage2(或者/boot)所在分区的文件系统;
stage1.5:存放于MBR之后的扇区,加载stage2所在分区的文件系统驱动,让stage1中的bootloader能识别stage2所在分区的文件系统;
stage2:存放于磁盘分区之上,具体存放于/boot/grub目录之下,主要用于加载内核文件(vmlinuz-VERSION-RELEASE)以及ramdisk这个临时根文件系统(centos5,6中的initrd-VERSION-RELEASE.img或centos7中的initramfs-VERSION-RELEASE.img).
grub功能及用途
(1)提供菜单并提供交互式接口
 e:编辑模式 c:命令行模式(cli)
(2)加载用户选择的操作系统或者内核,允许传递参数给内核,允许隐藏菜单
(3)为菜单提供保护机制,为编辑菜单提供保护机制,为启用内核或者操作系统提供认证
grub的配置文件目录
/boot/grub/grub.conf链接文件/etc/grub.conf-> ../boot/grub/grub.conf配置项参数:
 default=[index]:设定默认启动的菜单项,菜单项从0开始编号
 timeout=[num]:设定菜单项等待选择的时间,单位为秒
 splashimage=
(hd0,0)/grub/splash.xpm.gz:设定菜单的背景图片,格式较为特殊 hiddenmenu:隐藏菜单
 password [--md5] STRING:菜单编辑认证
 该md5值可以使用
grub-md5-crypt命令生成 title TITLE:自定义菜单项的标题
 root (hd#,#):grub查找stage2以及Kernel文件所在的设备分区
 kernel /PATH/TO/VMLINUXZ [parameters]:所要启动的内核
 常用参数:ro(只读方式),root=UUID=xxx(指明/sbin/init所在分区信息),quite
 initrd /PATH/TO/INITRAMFS:内核所匹配的ramfs文件
 password [--md5] STRIN:为所要启动的系统或者内核提供认证
手动在grub命令行接口启动服务:
 grub > root (hd#,#)
 grub > kernel /vmlinuz-VERSION-release ro root=/dev/DEVICE
 grub > initrf /initramfs-VERSION-relaese.img
 grub > boot
grub其他
进入单用户模式:
(1)编辑grub菜单(选定要编辑的菜单,然后使用e命令)
(2)选定Kernel后附加 1,s,S或者single都可以
(3)最后在Kernel所在行,使用b命令
* grub的安装/修复:
(1)grub-install,
grub-install --root-directory=ROOT /dev/DISK(2)grub命令行(按下ESC键进入):
 grub > root (hd#,#)
 grub > setup (hd#)
(3)载入安装光盘,进入救援模式(boot:
linux rescue)或者直接选定,类似于winpe# 切换根 chroot /mnt/sysimage # 执行grub-install命令 grub-install --root-directory=/ /dev/sda # 退出重启即可- 练习时破坏bootloader分区使用的命令:
dd if=/dev/zero of=/dev/sda bs=200 count=1,sync 
- 练习时破坏bootloader分区使用的命令:
 ramdisk:ramdisk是用于实现系统初始化的、基于内存的磁盘设备,即加载至内存的某一段空间后把内存当磁盘使用,并在内存中作为临时根文件系统提供给内核使用,帮助内核挂载真正的根文件系统。而之所以能够帮助内核挂载根文件系统是因为在ramdisk这个临时文件系统的/lib/modules目录下有真正的根文件系统所在设备的驱动程序.ramdisk文件的管理
(1)mkinitrd命令,为当前内核重新制作remdisk文件
options: [--preload <module>] # initramfs所提供要预先装载的模块. [--with=<module>] # 除了默认的模块还需要装载的模块. <initrd-image> <kernel-version>例子:
mkinitrd /boot/initramfs-${uname -r }.img ${uname -r}(2)dracut命令
例子:
dracut /boot/initramfs-${uname -r}.img ${uname -r}
Kernel:Kernel自身初始化,其主要作用有:
- 探测可识别到的所有硬件设备**bootloader将系统控制权移交给内核,探测bootloader留下的资源等
 - 加载硬件驱动程序,即加载真正的根文件系统所在设备的驱动程序(有可能会借助于ramdisk加载驱动)**内核探测出各项资源后,开启或关闭一些进程
 - 以只读方式挂载根文件系统;**如果有借助于ramdisk这个临时文件系统(虚根),则在这一步之后会执行根切换,否则不执行根切换
 - 运行用户空间的第一个应用程序:/sbin/init.**到这里
内核空间的的启动流程就结束了,而接下来是用户空间完成后续的系统启动流程 
/sbin/init(用户空间的第一个程序):虽然CentOS 5、CentOS 6以及CentOS 7的init配置 文件各不相同,一般配置文件:/etc/inittab, /etc/init/*.conf) ,但总体的启动流程是不变的.
根据init的配置文件设置默认运行级别
CentOS 5:初始化程序init是
SysV init,其配置文件为:/etc/inittabCentOS 6:初始化程序init是
upstart(模仿Ubuntu启动程序),其配置文件为:/etc/inittab, /etc/init/*.conf,也就是upstart将配置文件拆分成多个,在/etc/init/目录下以conf结尾的都是upstart风格的配置文件,而/etc/inittab仅用于设置默认运行级别
*.conf文件为upstart风格的配置文件,rcS.conf,rc.conf,start.ttys.confCentOS 7:初始化程序init是
systemd,其配置文件为:/usr/lib/system/systemd/, /etc/systemd/system/*
运行级别(0-6)
 0:关机模式,shutdown,对应
poweroff.target 1:单用户模式(single user):不需要通过认证,登录进去之后为root用户身份,属于维护模式,对应
rescue.target 2:多用户模式(multi user):会启动网络功能,但不会启动NFS,是维护模式,对应
multi-user.target 3:多用户模式(multi user):为完全功能模式,提供文本界面(minimal install default),对应
multi-user.target 4:预留级别,目前无特别使用目的,但习惯上以同3级别功能来使用,对应
multi-user.target 5:多用户模式(multi user):为完全功能模式,提供图形界面,对应
graphical.target 6:重启模式,reboot,对应
reboot.target
获取当前运行级别:
runlevel或者who -r级别之间的切换:
systemctl isolate TYPE.target或者init RUNLEVEL查看当前系统所有运行级别:
systemctl list-units -t target -a获取系统默认运行级别:
systemctl get-default修改当前系统默认运行级别:
systemctl set-default TYPE.target切换紧急救援模式:
systemctl rescue切换emergency模式:
systemctl emergency其他常用命令:
 关机:
systemctl poweroff或者systemctl halt 挂起:
systemctl suspend 快照:
systemctl hibernate 挂起并快照:
systemctl hybrid-sleep
补充
/etc/inittab文件对于CentOS5/6:
每行定义一种action以及与之对应的process: 格式:id:runlevel:action:process 各字段解释: id:一个任务的标识符; runlevel:在哪些级别下启动该任务;格式可以是#,###,也可以为空(表示所有级别); action:在什么条件下启动该任务; process:任务command;action种类: wait:等待切换至该任务所在的级别时执行一次; respawn:一旦该任务终止,就会重新启动这个任务; initdefault:设定默认运行级别;此时process是省略掉的; sysinit:设定系统初始化方式,这里一般指定为/etc/rc.d/rc.sysinit脚本文件;例如:
id:3:initdefault://设置默认运行级别,此处设置为3;注意:
CentOS 7使用target代替了runlevel,也就是在CentOS 7系列已经没有了运行等级这一概念了。而如果需要设置target则可参考该文件的后两行注释,详情见
/etc/inittab文件
运行系统初始化脚本
/etc/rc.d/rc.sysinit,完成系统初始化CentOS5/6
 ①设置主机名;
 ②设置欢迎信息;
 ③激活udev和selinux;
 ④挂载/etc/fstab文件中定义的所有文件系统;
 ⑤检测根文件系统,以读写方式重新挂载根文件系统;
 ⑥设置系统时钟;
 ⑦根据/etc/sysctl.conf文件来设置内核参数;
 ⑧激活lvm及软raid设备;
 ⑨激活swap设备;
 ⑩加载额外设备的驱动程序(因为内核只加载根文件系统所在分区的驱动程序);
 ⑪清理操作;
注意:
CentOS7中无,欢迎信息文件为
/etc/issue,文件内容详解https://www.cnblogs.com/cnjavahome/p/8476462.html
2. Linux内核
内核设计体系:单内核和微内核
linux采用的是单内核设计,但其充分借鉴了微内核体系设计的优点,为内核引入了
模块化机制. 内核的组成部分:
 Kernel:内核核心部分,一般为bzimage压缩镜像格式,位于
/boot目录,其名称为vmlinuz-VERSION-release Kernel object(*.ko文件):内核对象,即内核模块,一般位于
/lib/modules/VERSION-release ramdisk文件:CentOS5:
/boot/initrd-VERSION-release,CentOS6:/boot/initramfs-VERSION-release 编译内核所用到的标识:
 [ ]:N
:Module  [*]:Y 编译进内核
内核信息的获取,使用命令
uname -r内核模块查看命令:
lsmod(显示信息来源于/proc/module),modinfo(例:modinfo [-F] [-n] ipt_REJECT)内核模块的动态装卸载:
modprobe [-r] module_name,选项-r代表卸载模块insmod [filename] [module options]...,filename表示模块文件的路径;rmmod [module_name],卸载.
ldd命令:ldd [OPTION]... FILE... 打印二进制程序文件的依赖模块- 使用
ldd [二进制可运行文件绝对路径] | grep -o "/lib[^[:space:]]*"可以快速查看依赖模块的路径 
- 使用
 内核的简单编译流程:
(1)获取目标主机上硬件设备的相关信息
# CPU有关信息 cat /proc/info lscpu x86info -a # 详细 # PCI设备 lspci lsusb lsblk # 获取所有硬件设备信息 hal-device(2)根据平台去官网https://www.kernel.org/下载适合的内核
(3)准备编译环境,所需包组
Development Tools,Server Platform Development,可能还需要ncurses-devel,如需使用窗口界面进行内核编译,还需要Desktop Platform Development包组(4)解压内核至
/usr/src目录,并创建一个软连接ln -sv linux(5)配置内核选项,使用tui来配置
make menuconfig(6)编译,
make [-j #],其中#代表线程数,设置该参数可以进行多线程编译几种编译模式:
支持以更新模式进行配置:在已有的.config文件基础上进行修改配置
(a)
make config:基于命令行遍历的方式去配置内核中的每个选项(b)
make menuconfig: 基于cureses的文本配置窗口(c)
make gconfig:基于GTK开发环境的窗口界面,所属包组桌面平台开发(d)
make xcongfig:基于QT开发环境的窗口界面支持全新配置模式进行配置:
(e)
make defconfig:基于内核为目标平台提供的默认配置进行配置(f)
make allnoconfig:所有选项均不选中
部分编译:
(1)只编译子目录中的相关代码
cd /usr/src/linux make PATH/TO/DIR(2)只编译某个特定的模块
cd /usr/src/linux make PATH/TO/DIR/file.ko(7)
make modules_install,安装内核模块(8)
make install,安装内核
内核信息输出的伪文件系统
/proc内核信息和统计信息的输出接口,其配置接口为/proc/sys在
/proc/sys目录中
net/ipv4/ip_forward相当于net.ipv4.ip_forward参数设置方式:
(1)
sysctl命令:用于查看/proc/sys目录下的参数的值 查看所有内核参数:
sysctl -a 查看单个内核参数:
sysctl VARIABLE 修改:
sysctl -w VARIABLE=value(2)使用文件系统相关命令,
cat和echo 查看:
cat /proc/sys/PATH/TO/FILE 修改:
echo "value" > /proc/sys/PATH/TO/FILE注意:以上两种方式均为当前运行内核有效,重启后无效
(3)修改配置文件使其永久有效
/etc/sysctl.conf和/etc/sysctl.d/*.conf 立即生效的方式:
sysctl -p /PATH/TO/CONF_FILE
3. anaconda自动化安装脚本
CentOS系统安装流程(所使用的安装程序:
anaconda):概括流程:
BootLoader --> kernel(initrd(rootfs)) --> anaconda(有tui和gui配置窗口)
MBR:
boot.cat文件Stage2:isolinux/isolinux.bin
 配置文件:isolinux/isolinux.cfg
每个对应菜单选项:
 加载内核:isolinux/vmlinuz
 向内核传递参数:append initrd=initrd.img
装载根文件系统,并启动anaconda
安装阶段:
 对目标磁盘进行分区和格式化操作
 将指定的软件包安装至目标位置
 安装bootloader
首次启动:
 iptables
 selinux
 core dump
安装引导选项(1):
text:将以文本方式进行安装method:手动指定安装的方法 与网络相关的引导选项:
ip,netmask,gateway,dns例如:
linux method ip=192.168.1.43 netmask=255.255.255.0 gateway=192.168.1.1 dns=192.168.1.1 远程访问功能相关配置:
vnc和vncpassword=YOUR_VNC_PASSWORDrescue:启用紧急救援模式
一般使用ISO光盘镜像安装的系统会在用户根目录生成一个名为
anaconda-ks.cfg的文件,该文件即为kickstart文件安装引导选项(2):
ks:指明kickstart文件的位置ks=
 DVD drirve:ks=cdrom:/PATH/TO/KICKSART_FILE
 此外还支持
hard driver,http server,FTP server和nfs server等kickstart文件的参数及格式(详情参见https://anaconda-installer.readthedocs.io/en/latest/index.html):(1)命令段:指定各种安装前的配置选项,如键盘类型,语言编码等...
(2)程序包段:指明要安装的程序包,包组,和一些不需要安装的程序包
%package # start @group_name # 包组 package # 所要安装的包 -package # 不需要安装的包 %end # end(3)脚本段:
%pre:安装前所要运行的脚本
%post:安装后所要运行的脚本
其他参见
anaconda-kick部分参数.txt文件
最后使用
ksvalidatorfilename来检查语法错误通过网络http服务器中kickstart文件安装
(1)挂载光盘镜像,开进进入安装界面
(2)按下ESC键进入boot命令行,输入以下命令:
linux ip=192.168.1.231 netmask=255.255.255.0 gateway=192.168.1.1 ks=https://192.168.1.1/centos6.x86_64.cfg即可
通过光盘镜像进行引导安装
(1)挂载光盘,将光盘根目录下的
isolinux文件复制出来(2)将复制出来的
isolinux文件夹内的所有文件授予写权限cd isolinux/ chmod +w *(3)将准备好的
anaconda-ks.cfg文件放在与isolinux文件夹同级的目录之下(4)制作光盘镜像
mkisofs -R -J -T -v --no-emul-boot --boot-load-size 4 --boot-info-table -V "CentOS 6 x86_64 boot" -c isolinux/boot.cat -b isolinux/isolinux.bin -o /root/boot.iso myboot/ # 输出文件boot.iso,isolinux和ks文件置于myboot目录下(5)打开目标机器并挂载上一步输出的
boot.iso文件,按下tab键输入以下内容:vmlinuz initrd=initrd.img ks=cdrom:/anaconda-ks.cfg ip=YOUR_IP netmask=YOUR_NETMASK或者直接修改
isolinux目录下的isolinux.cfg文件,避免手动输入ks仓库地址append initrd=initrd.img ks=cdrom:/anaconda-ks.cfg然后重新使用第四步中的命令重新生成iso镜像文件即可
4. 小练习
自行创建一个Linux引导系统,并且能够使用
(1)增加一块目标硬盘(虚拟硬盘)
(2)进行分区和格式化操作
fdisk /dev/sdb # 创建三个分区,依次是boot,swap和根分区 kpartx /dev/sdb # 强制让内核重读分区 # 格式化分区 mke2fs -t ext4 /dev/sdb1 # 同理/dev/sdb3 mkswap /dev/sdb2 # 格式化swap分区(3)分别挂载sdb1和sdb3至
/mnt/boot和/mnt/sysroot(4)在boot目录下安装grub
grub-install --root-directory=/mnt /dev/sdb(5)拷贝vmlinuxz文件和initramfs文件到boot目录
cp /boot/vmlinuz-2.6.32-754.el6.x86_64 ../vmlinuz cp /boot/initramfs-2.6.32-754.el6.x86_64.img initramfs.img(6)编辑
/grub/grub.conf文件,内容如下:default=0 timeout=5 title CentOS6_TEST root (hd0,0) kernel /vmlinuz ro root=/dev/sda3 selinux=0 init=/bin/bash # 原内核中的seLinux应该先取消 initrd /initramfs.img(7)为sysroot创建linux文件目录
mkdir -pv etc bin sbin lib lib64 dev proc tmp var usr home root sys media mnt(8)使用ldd命令放入必要二进制文件
ldd /bin/bash | grep -o "/lib[^[:space:]]*" cp ××× {相应目录下} # 使用chroot测试(9)重新装载到目标机器即可使用