一、Linux内核的组成
相关概念:
Linux系统的组成部分:内核+根文件系统
内核功能包括进程管理、内存管理、网络协议栈、文件系统、驱动程序、安全功能
IPC:Inter Process Communication进程间通讯
指至少两个进程或线程间传送数据或信号的一些技术或方法。进程是计算机系统分配资源的最小单位(严格说来是线程)。每个进程都有自己的一部分独立的系统资源,彼此是隔离的。为了能使不同的进程互相访问资源并进行协调工作,才有了进程间通信。通常,使用进程间通信的两个应用可以被分为客户端和服务器(见主从式架构),客户端进程请求数据,服务端响应客户端的数据请求。有一些应用本身既是服务器又是客户端,这在分布式计算中,时常可以见到。这些进程可以运行在同一计算机上或网络连接的不同计算机上。
IPC包括消息队列、信号灯、以及共享内存区(Message queues, semaphores, and shared memory)(本地间通讯)
socket(跨主机通信)
运行中的系统环境可分成两层:内核空间、用户空间
用户空间:应用程序(进程或线程)
内核空间:内核代码(系统调用)
内核设计流派:
单内核设计:把所有功能集成于同一个程序;
例如:Linux
微内核设计:每种功能使用一个单独的子系统实现
例如:Windows,Solaris
Linux内核特点:
虽然是单内核设计,但支持模块化并支持模块运行时动态装载或卸载
模块文件通常为 .ko(kernel object)内核模块(对象)
Linux对象类文件有两种 .so(share object)/共享对象 供各种应用程序之间共享的应用模块另一种就是.ko 没有共享概念 只是作为内核中某一种功能实现
内核组成部分:
- 核心文件:/boot/vmlinuz-VERSION-release①
1.1 ramdisk(中间临时文件根系统,动态创建出来的,使用缓冲和缓存来加速对磁盘上的文件访问):
安装操作系统后临时生成的文件,能够扫描当前操作系统的硬盘驱动,装载对应的模块 用于实现系统初始化的基于内存的磁盘设备,把内存中的一段空间当内存使用
ramdisk:②
Linux内核的特性之一:使用缓冲和缓存来加速对磁盘上的文件访问
ramdisk --> ramfs
CentOS5:initrd
工具程序:mkinitrd
CentOS 6,7:initramfsA
工具程序:dracut,mkinitrd 借助ramdisk驱动根文件系统
CentOS 5:/boot/initrd-VERSION-release.img
CentOS 6,7:/boot/initramfs-VERSION-release.img - 模块文件:/lib/modules/VERSION-release
安装多个内核版本 那么该文件目录下 就会有多个内核文件目录
二、CentOS系统启动流程(仅适用于PC架构且硬盘为MBR格式主机)
1、POST③加电自检
主要实现的功能是检测各个外围硬件设备是否存在而且能够正常运行起来,实现这一自检功能的是固化在主板上的ROM④(主要代表为CMOS)芯片上的BIOS(Basic Input/Output System)⑤程序;透过BIOS程序加载CMOS的信息,并藉由CMOS内的设定值取得主机的各项硬件配置、例如 CPU 与接口设备的沟通频率、
开机装置的搜寻顺序、硬盘的大小与类型、 系统时间、各周边总线的是否启动 Plug and Play
(PnP, 即插即用装置) 、 各接口设备的 I/O 地址、以及与 CPU 沟通的 IRQ 岔断等等的信息只要一通电,CPU就会自动去加载ROM芯片上的BIOS程序,是这样来实现的。
在整个操作系统中,可被寻址的物理存储空间由两部分组成ROM,RAM
需要通过ROM加载自检程序也就是说CPU所访问的物理地址空间不光有物理内存,还包括ROM
2、Boot Sequence
按次序查找各引导设备,第一个有引导程序的设备即为本次启动要用到的设备
3、bootloader
引导加载器是一个程序 可以安装在硬盘 光盘 甚至是硬盘上的程序
- Windows:ntloader
- Linux:
2.1 LILO:Linux Loader 短小精悍的linux加载器,1024柱面之后无法加载,现在多用于安卓手机启动
2.2 GRUB:Grand Unified Bootloader/通用统一引导加载器
GRUB 0.X 被称为 Grub Legacy
GRUB 1.X 与0.X相距甚远 被称为 Grub2
功能:提供一个菜单,允许用户选择要启动的系统或不同的内核版本;把用户选定的内核装载到RAM中的特定空间中,解压,展开,而后把系统控制权交给内核;
MBR(Master Boot Record) MBR记录一般是在磁盘 0 磁道 1 扇区,共512个字节。前446个字节是BootLoder,后 4*16 的 64 个字节是存放分区信息的,最后 2 个字节是校验信息,一般是 55AA。
grub是bootloader中的一种,就grub来说,为了打破在MBR中只有446Bytes用于存放bootloader这一限制,所以这一步的实现是这样的:grub是通过分成三个阶段来实现加载内核这一功能的,这三个阶段分别是:stage1, stage1.5以及stage2。其中:
- stage1:存放于MBR的前446Bytes,用于加载stage1.5阶段,目的是为了识别并驱动stage2(或者/boot)所在分区的文件系统;
- stage1.5:存放于MBR之后的扇区,加载stage2所在分区的文件系统驱动,让stage1中的bootloader能识别stage2所在分区的文件系统;
- stage2:存放于磁盘分区之上,具体存放于/boot/grub目录之下,主要用于加载内核文件(vmlinuz-VERSION-RELEASE)以及ramdisk这个临时根文件系统(initrd-VERSION-RELEASE.img或initramfs-VERSION-RELEASE.img)。
概述:假如要启动的是硬盘设备,首先我们的硬件平台主板BIOS必须能够识别硬盘,然后BIOS才能加载硬盘中的bootloader,而bootloader自身加载后就能够直接识别当前主机上的硬盘设备了;不过,能够识别硬盘设备不代表能够识别硬盘设备中的文件系统,因为文件系统是额外附加的一层软件组织的文件结构,所以要对接一种文件系统,就必须要有对应的能够识别和理解这种文件系统的驱动,这种驱动就称为文件系统驱动。而stage1.5就是向grub提供文件系统驱动的,这样stage1就能访问stage2及内核所在的分区(/boot)了。
用于取代MBR的设计架构 UEFI,GPT
4、Kernel
kernel自身初始化,实现功能:
- 探测可识别到的所有硬件设备
bootloader将系统控制权移交给内核就好比如后朝推翻前朝,统治者(内核)当权之后,首先要检查一下有哪些是前朝所留下的,例如有哪些领土、人力、财力、兵力可用等等。
- 加载硬件驱动程序;(有可能会借助于ramdisk加载驱动)
这就像统治者(内核)在得知底下存在的人力、财力之后,开始将可以“为我所用”的人力纳入麾下,听自己使唤,而不听使唤的杀掉;
- 以只读方式挂载根文件系统
如果有借助于ramdisk这个临时文件系统(虚根),则在这一步之后会执行根切换;否则不执行根切换。
- 运行用户空间的第一个应用程序:/sbin/init
到这里内核空间的启动流程就结束了,而接下来是用户空间完成后续的系统启动流程。
ramdisk和内核是由bootloader一同加载到内存当中的,ramdisk是用于实现系统初始化的、基于内存的磁盘设备,即加载至内存(的某一段空间)后把内存当
磁盘使用,并在内存中作为临时根文件系统提供给内核使用,帮助内核挂载真正的根文件系统。而之所以能够帮助内核挂载根文件系统是因为在ramdisk这个临
时文件系统的/lib/modules目录下有真正的根文件系统所在设备的驱动程序;除此之外,这个临时文件系统也遵循FHS,例如有这些固定目录结构:/bin,
/sbin, /lib, /lib64, /etc, /mnt, /media, ...
因为Linux内核有一个特性就是通过使用缓冲/缓存来达到加速对磁盘上文件的访问的目的,而ramdisk是加载到内存并模拟成磁盘来使用的,所以Linux就会为
内存中的“磁盘”再使用一层缓冲/缓存,但是我们的ramdisk本来就是内存,它只不过被当成硬盘来使用罢了,这就造成双缓冲/缓存了,而且不会起到提速效果
甚至影响了访问性能;CentOS 5系列以及之前版本的ramdisk文件为initrd-VERSION-RELEASE.img,就会出现上述所说到的问题;而为了解决一问题
CentOS 6/7系列版本就将其改为initramfs-VERSION-RELEASE.img,使用文件系统的方式就可以避免双缓冲/缓存了,我们可以说这是一种提速机制。
init程序的在不同CentOS版本上类型:
- CentOS 5及之前:SysV init
配置文件:/etc/inittab - CentOS 6:Upstart
配置文件:/etc/inittab(兼容CentOS5) /etc/init/*.conf - CentOS 7 :Systemd
配置文件:/usr/lib/systemd/system/,/etc/systemd/system
系统初始化流程(内核级别):POST --> BootSequence(BIOS) -->BootLoader(MBR) --> Kernel (ramdisk) -->rootfs(readonly加载)-->/sbin/init()
/sbin/init:
CentOS 5:SysV init
运行级别:为了系统的运行或维护等目的而设定的机制
0-6:7个级别
0、关机,shutdown
1、单用户模式(single user),root用户,无须认证;维护模式
2、多用户模式(multi user),会启动网络功能,但不会启动NFS;维护模式
3、多用户模式(mutli user),完全功能模式;文本界面
4、预留级别:目前无特别使用目的,但习惯以同3级别功能使用
5、多用户模式(multi user),完全功能模式,图形界面
6、重启,reboot
默认级别:3,5
级别切换:init #
级别查看:who -r
runlevel 3 5
上一次启动使用3级别 本次使用5级别
配置文件:/etc/inittab
每行定义一种action(操作)以及与之对应的process
- id:runlevels:action:process
id:一个任务的标识符
runlevels:在哪些级别启动此任务;#,###,也可以为空,表示所有级别
action:在什么条件下启动此任务;
process:任务 - action:
wait:等待切换至此任务所在的级别时执行一次;
respawn:此任务终止时,就自动重新启动之;
initdefault:设定默认运行级别;此时,process省略
sysinit:设定系统初始化方式,此处一般为指定的/etc/rc.d/rc.sysinit脚本(CentOS 56才有 7没有); - 例如:vim /etc/inittab
id:3:initdefault: <--默认的runlevel配置
si::sysinit:/etc/rc.d/rc.sysinit <--准备系统软件运行的环境脚本运行档
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
…………
l6:6:wait:/etc/rc.d/rc 6- /etc/rc.d/目录下有运行级别的目录
意味着去启动或关闭/etc/rc.d/rc3.d/目录下的服务脚本所控制服务
K:要停止的服务;K##,优先级,数字越小,越是优先关闭;依赖的服务先关闭,而后关闭被依赖的;
S:要启动的服务;S##,优先级,数字越小,越是优先启动;被依赖的服务先启动,而后依赖的服务后启动
- /etc/rc.d/目录下有运行级别的目录
- 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}
为了控制服务启动 需要一个统一的管控接口(服务脚本)
# service SRV_SCRIPT {start|stop|restart|status}
- chkconfig命令:管控/etc/init.d/每个服务脚本在各级别下的启动或关闭状态;
查看:chkconfig --list [name]
添加:chkconfig --add name
删除:chkconfig --del name
能被添加的服务的脚本定义格式之一:
#!/bin/bash
#
#chkconfig: LLL NN MM
LLL表示runlevel:处于该level下服务自启动
NN:表示启动优先级
MM:表示关闭优先级
- 修改指定的链接类型:
chkconfig [--level LEVELS] name <on|off|reset>
--level LEVELS:指定要控制的级别
- 若直接chkconfig name on 则默认在2345级别启动
注意:正常级别下(3,5)下,最后启动的一个服务S99local没有链接至/etc/init.d下某脚本,而是链接至/etc/rc.d/rc.loca(/etc/rc.lcoal)l脚本,因此,不便或不需写为服务脚本的程序期望能开机自动运行时,直接放置于此脚本文件中即可
tty1:2345:respawn:/usr/sbin/mingetty tty1
…………
tty6:2345:respawn:/usr/sbin/mingetty tty6
- 当处于2345等运行级别时启动/usr/sbin/mingetty程序(虚拟终端) 这就是为什么可以按Ctrl+Alt+F1-6能切换并打开虚拟终端的原因
- 登陆时,mingetty会调用login程序
- 打开虚拟终端的程序除了mingetty之外,还有诸如getty等;
- 系统初始化脚本:/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、清理操作
注意:CentOS 7的systemd可能没有这一步,而是通过其他机制来实现。
总结(用户空间的启动流程):/sbin/init(/etc/inittab)
设置默认运行级别--> 运行系统初始化脚本,完成系统初始化-->关闭对应级别下需要停止的服务,启动对应级别下需要开启的服务-->设置登陆终端[-->启动图形终端]
这一切进程都有init或init子进程启动 这就是为什么pstree都是init子进程的原因
以上是CentOS5的启动流程
CentOS6启动流程:
- init程序:upstart,但依然为/sbin/init,其配置文件;
- /etc/init/*.conf,/etc/inittab(仅定义系统启动级别)
- /etc/init/rsS.conf即为系统初始化脚本
- /etc/init/start-ttys.conf即为启动终端脚本
- /etc/init/[rc init-system-dbus].conf 启动服务脚本 rc.conf为主脚本
注意:*.conf为upstart风格的配置文件;无需深入学习 CentOS7没有该风格
- /etc/init/*.conf,/etc/inittab(仅定义系统启动级别)
CentOS7启动流程:
- init程序:systemd,配置文件:/usr/lib/systemd/system/,/etc/systemd/system/
完全兼容SysV脚本机制;因此,service命令依然可用;不过,建议使用systemctl命令来控制服务;
# systemctl {start|stop|restart|status} name[.service]
思维导图
注:
附加资源
CentOS系列启动流程和内核原理(5系列,6系列,7系列)
①vmlinuz:表示此内核文件为压缩文件 VERSION:内核版本号 release:local version 本地版本号
②在早期的Linux系统中,一般就只有软盘或者硬盘被用来作为Linux的根文件系统,因此很容易把这些设备的驱动程序集成到内核中。但是现在根文件系统 可能保存在各种存储设备上,包括SCSI, SATA, U盘等等。因此把这些设备驱动程序全部编译到内核中显得不太方便。
在Linux内核模块自动加载机制的介绍中,我们看到利用udevd可以实现实现内核模块的自动加载,因此我们希望根文件系统的设备驱动程序也能够实现自动加载。但是这里有一个矛盾,udevd是一个可执行文件,在根文件系统被挂载前,是不 可能执行udevd的,但是如果udevd没有启动,那就无法自动加载根根据系统设备的驱动程序,同时也无法在/dev目录下建立相应的设备节点。
为了解决这个矛盾,于是出现了initrd(boot loader initialized RAM disk)。initrd是一个被压缩过的小型根目录,这个目录中包含了启动阶段中必须的驱动模块,可执行文件和启动脚本。包括上面提到的udevd,当 系统启动的时候,booload会把initrd文件读到内存中,然后把initrd的起始地址告诉内核。内核在运行过程中会解压initrd,然后把 initrd挂载为根目录,然后执行根目录中的/initrc脚本,您可以在这个脚本中运行initrd中的udevd,让它来自动加载设备驱动程序以及 在/dev目录下建立必要的设备节点。在udevd自动加载磁盘驱动程序之后,就可以mount真正的根目录,并切换到这个根目录中。
③加电自检又称为引导自我检测(英语:Power-On Self-Test;POST),是计算机BIOS的一个功能,在引导后会运行,针对计算机硬件如CPU、主板、存储器等进行检测,结果会显示在固件可以控制的输出接口,像显示屏、LED、打印机等等设备上。加电自检的检查速度极快,甚至感受不到它的存在。
④Rom(Read Only Memory)只读存储器,这种存储器(Memory)的内容任何情况下都不会改变,计算机与用户只能读取保存在这里的指令,和使用存储在ROM的数据,但不能变更或存入数据。ROM被存储在一个非易失性芯片上,也就是说,即使在关机之后记忆的内容仍可以被保存,所以这种存储器多用来存储特定功能的程序或系统程序。
CMOS(互补式金属氧化物半导体) 早期的只读存储器主要就是以这种电路制作的,由于当时电脑系统的BIOS程序和参数信息都保存在ROM和SRAM中,以致在很多情况下,当人们提到“CMOS”时,实际上指的是电脑系统之中的BIOS单元,而一般的“CMOS设置”就是意指在设定BIOS的内容。
BIOS是计算机上另一个重要的存储器。之所以提到它,是因为互补式金属氧化物半导体中保存着BIOS程序的设置结果。而且,互补式金属氧化物半导体中的用户信息和常规设置需要在BIOS程序引导计算机启动后才能载入。
⑤BIOS用于计算机引导时运行系统各部分的自我检测(Power On Self Test),并加载引导程序(IPL)或存储在主存的操作系统。此外,BIOS还向操作系统提供一些系统参数。系统硬件的变化是由BIOS隐藏,程序使用BIOS功能而不是直接控制硬件。现代操作系统会忽略BIOS提供的抽象层并直接控制硬件组件。