Back to Linux Kernel

See Also: SysV-style

Linux Startup Process

Linux系统的启动过程是一个多级初始化过程。Linux startup process派生自Unix,因此引导过程在形式上非常类似于BSD和其他Unix。

Linux系统的引导涉及多个阶段和软件组件,包括:

  1. 固件初始化(Firmware Initialization)
  2. 执行引导加载程序(Boot Loader)
  3. 加载和启动Linux内核映像(Linux kernel image)
  4. 执行各种启动脚本和守护进程(Startup Scripts and Daemons)

每个阶段和组件可能采用不同的方法和变化,例如

1. Early User Space

initramfs,也称为早期用户空间,从V2.5.46版本开始引入到Linux内核中,用来取代之前内核会在启动过程中执行的尽可能多的功能。早期的用户空间的典型用途是检测并确定哪些设备驱动程序需要加载,并从临时的文件系统加载到主要用户空间文件系统。

1.1. initramfs

initramfs,"initial ram file system"的缩写,是initrd的继任者。在Linux启动过程中,initramfs作为cpio归档的最初文件系统加载到内存中。Linux内核挂载它作为根文件系统来启动init进程。因为需要在真正的根文件系统加载前前完成任务,initramfs需要包含所有的设备驱动程序和工具以完成挂载真正的根文件系统的工作。

对于某些应用程序,initramfs可以利用casper工具来创建一个可写的环境--使用一个unionfs文件系统覆盖在只读的根文件系统映像上。覆盖数据可以存储在U盘上,而压缩的SquashFS文件系统存储在一个live CD作为根文件系统。

initramfs是一个“鸡生蛋||蛋生鸡”问题的解决方案:对于大规模存储设备和文件系统--特别是加密文件系统,需要复杂的设备驱动程序来读取数据,而设备驱动程序通常存储在文件系统的大容量存储器上。

2. Boot Loader Phase

2.1. GRUB

GRUB

  1. 第一阶段的加载程序(stage1):被BIOS从主引导记录(MBR)或被另一个引导加载程序从分区的引导扇区加载和执行;
  2. 如果有必要,Stage1会加载和执行一个中间阶段加载程序(stage1.5)。这可能是必要的,如果第二阶段加载程序不连续,或文件系统、硬件需要特殊处理才能得第二阶段加载程序;
  3. 然后第二阶段加载程序(stage2)被加载和执行。显示GRUB启动菜单,允许用户选择一个操作系统或检查和编辑启动参数;
  4. 选好操作系统后,GRUB加载内核到内存,将控制权交给内核。另外,通过使用链式加载,GRUB可以把启动过程控制权交给其它引导加载程序。

2.2. LILO

一个很古老的加载程序。

2.3. SYSLINUX

SYSLINUX基于FAT文件系统,一般不用于启动完整的Linux系统。它通常用于引导或救援盘、live USBs或其他轻量级引导系统。ISOLINUX通常使用Linux live cd和引导安装光盘。

3. Kernel Phase

Linux内核处理所有操作系统进程,如

在装载上分为两个阶段:

3.1. Kernel loading stage

加载的内核通常是一个镜像文件,用zlib压缩成zImage或bzImage格式。包含常规的少量的硬件设置,解压缩镜像到高位内存,配置需要注意的任何RAM磁盘。然后通过./arch/i386/boot/headstartup_32 ()执行内核启动。

3.1.1. vmlinux

在linux系统中,vmlinux(vmlinuz)是一个包含linux kernel的静态链接的可执行文件,文件型态可能是linux接受的可执行文件格式之一(ELF、COFF或a.out),vmlinux若要用于除错时则必须要在开机前增加symbol table。

Linux kernel boot and decompression process

3.1.1.1. vmlinuz

vmlinuz 是vmlinux 经过 gzip和objcopy 制作出来的压缩文件,当然不再是vmlinux的一个简单的压缩版,这么简单。vmlinuz是一种统称,有两种具体的表现形式zImage 和bzImage。bzimage和zImage的区别在于本身的大小,以及加载到内存时的地址不同,zImage在0~640KB,而bzImage则在1M以上的位置!

3.1.1.2. vmlinux.bin

vmlinux.bin 是进行如下操作得来,除二进制内容一无所有,而vmlinx是elf格式的文件里面包含了elf头部内容:

#objcopy -O binary vmlinux vmlinux.bin.

3.1.1.3. bzImage

随着linux Kernel的成长,核心的内容日益增加超越了原本的限制大小。bzImage (big zImage) 格式则为了克服此缺点开始发展,利用将核心切割成不连续的存储器区块来克服大小限制。

3.2. Kernel startup stage

内核的启动函数(也称为swapper或process0)建立内存管理(分页表和内存分页),检测到CPU的类型和任何额外的功能(如浮点功能),然后通过调用start_kernel()切换到non-architecture的Linux内核功能。

start_kernel执行大量的初始化函数:

值得注意的是,内核启动过程也挂载初始RAM磁盘(initrd),在启动阶段加载之前的临时根文件系统。

因此,内核初始化设备、挂载引导加载程序指定为只读的根文件系统,并运行Init(/sbin/init)--系统中的第一个进程(PID = 1)。

3.3. 更多参考

4. Init Process

截至2014年2月,很多Linux发行版,比如Debian/Arch/Fedora和openSUSE,已经使用systemd替代init进程作为初试进程在用户空间执行Linux启动。同时,systemd取代了传统的基于shell脚本的init系统,使用一组守护进程以及自己的初始化指令,记录在声明式配置文件。

4.1. SysV init

Init是所有进程的父亲。它的主要作用是根据脚本创建进程,创建脚本存储在文件/etc/inittab。这个文件一般会有访问入口--init spawn出终端(getty)允许用户登录。

init还控制特定系统所需的自治进程(autonomous process)。运行级别(run level)是一种软件的配置系统,只允许存在一组被选的过程。被init spawned的进程的运行基本在/etc/inittab文件中定义。

$ sudo cat /etc/inittab
id:3:initdefault:

是 Unix 和 类Unix 系统中用来产生其它所有进程的程序。它以守护进程的方式存在,其进程号为1。

init风格:

4.2. systemd

systemd是Linux下的一种init软件,由Lennart Poettering带头开发,并在LGPL 2.1及其后续版本许可证下开源发布。其开发目标是提供更优秀的框架以表示系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动,同时达到降低Shell的系统开销的效果,最终代替现在常用的System V与BSD风格init程序。

与多数发行版使用的System V风格init相比,systemd采用了以下新技术:

从设计构思上说,由于systemd使用了cgroup与fanotify等组件以实现其特性,所以只适用于Linux[5]。有鉴于此,考虑到kFreeBSD分支的软件源无法纳入systemd,为与其他分支保持一致,Debian开发者尽力避免纳入systemd。但Lennart Poettering本人对此并不在意,并称“Debian GNU/kFreeBSD不过是玩具系统”。

默认init程序为systemd的发行版

可以使用systemd的发行版

4.3. Upstart

Upstart是一个基于事件的初始化守护进程,用于替代传统的init(多种类Unix计算机操作系统启动时用于执行任务的程序)。它是由Canonical公司前雇员Scott James Remnant所写。

传统的init进程原本只负责在开机后将计算机带入正常运行状态,并且在正常关机前关闭服务。因此,它的设计是严格同步的,且会阻塞未来的任务,直到完成当前任务。因为受限于准备或清除函数,它的任务也是事先定义的。这使得它无法简洁地处理现代桌面计算机上的各种非启动任务,其中包括:

Upstart的事件驱动模型允许它以异步方式对生成的事件作出回应。

4.3.1. 设计

Upstart是异步工作的;它在系统运行时监督服务,并且在开关机时启动和关闭任务和服务。

对sysvinit简单的过渡和完善的向后兼容是明确的设计目标;因此,Upstart能运行未经修改的sysvinit脚本。因此,与大多数其他的init替代(除了systemd和OpenRC)不同,它们通常假设并要求彻底的过渡,以正常运行,且不支持新旧启动方法混合的环境。

通过使用initctl输入自定义的单一事件,或整合更多更复杂事件的事件桥,Upstart允许扩展其事件模型。默认情况下,Upstart包括接口(socket)、dbus、udev、文件及dconf事件桥;另外,可以有更多种桥(例如Mach端口桥,或devd(FreeBSD系统上)桥)。

4.3.2. chkconfig

# Check if service is enabled or disabled on startup:
$ chkconfig --list | grep SERVICE

# Disable service autostart in CentOS-6:
$ chkconfig SERVICE off

# Enable service autostart in CentOS-6:
$ chkconfig SERVICE on

4.4. runit

Runit是类Unix操作系统上的一个init方案,为整个操作系统初始化、监督和结束进程。这是一个“重新实现”的“再生”过程监控工具,运行在Linux/Mac OS X/*BSD和Solaris操作系统上。Runit并行化系统服务的启动特性,可以加快操作系统的启动时间。

Runit是一个init守护进程,因此它是所有其他进程的直接或间接祖先。它是系统启动后第一个开始的进程,持续运行直到系统关闭。

4.5. launchd

launchd是一个统一的、开源的服务管理框架,在Apple OS X系统下用于开始、停止并管理守护进程,、应用程序、进程。Dave Zarzycki在苹果时设计和编写了launchd;苹果从Mac OS X Tiger开始引入,采用Apache License。

在Mac OS X v10.4之前,系统由Mac OS X的BSD风格init启动,在Mac OS X v10.4及其后续版本中,由launchd启动。

5. Reference


CategoryLinux

MainWiki: Linux_Startup_Process (last edited 2015-01-16 01:54:27 by twotwo)