一、启动总流程图
kernel和initrd: 探测硬件->加载驱动(initrd, 微型linux)->挂载根文件系统->rootfs(/sbin/init) 。initrd不是必须的。
二、三个主要的init
讲述三个主要的 Init 系统:sysvinit,UpStart 和 systemd
1、sysvinit
SysVinit 顺序运行(串行),概念简单清晰、启动慢。启动流程如下:
init--->inittab(runlevel)--->rc.sysinit(系统初始化)--->rc--->rcX.d(启停服务)--->rc.local--->tty和login
缺点:频繁地使用硬件热插拔技术,sysvinit需要默认就启动所有可能使用的硬件对应的服务;网络共享盘的挂载(nfs、iSCSI),需要netfs 服务来挂载所有这些网络盘;启动慢。
2、upstart
Upstart 采用事件驱动模型。更快地启动系统(并行);当新硬件被发现时动态启动服务;硬件被拔除时动态停止服务。
UpStart 主要的概念是 job 和 event。Job 就是一个工作单元,用来完成一件工作,比如启动一个后台服务,或者运行一个配置命令。每个 Job 都等待一个或多个事件,一旦事件发生,upstart 就触发该 job 完成相应的工作。
开机upstart首先产生startup事件。
3、systemd
systemd 的最大特点有两个:
(1)、提供了比 UpStart 更激进的并行启动能力,采用了 socket / D-Bus activation 等技术启动服务。结果就是:更快的启动速度。
(2)、用 CGroup 统计跟踪子进程,干净可靠。
3.1、并行化Socket
对于传统的 Unix daemon,彼此的真正依赖是服务所提供的 socket。
如果能尽早建立客户程序所必须的 socket 而令客户程序处于等待状态而不是在服务程序完全启动后再启动客户程序,我们就能加快启动进程,进一步并行化进程启动。
3.2、并行化Bus服务
Linux上现代的daemon都通过DBus而非socket来交互。
DBus已经提供了所有必要的hook:使用DBus将会在第一次访问时加载服务,并且给予最小的、每请求一个的、消费 者与生产者同时启动的同步机制。
例如Avahi与CUPS(CUPS需要Avahi进行 mDNS/DNS-SD上打印机扫描)同时启动,仅仅是简单的同时启动二者,若CUPS比Avahi启动快,则DBus将把请求缓存入队列,直到 Avahi服务进行了处理。
总结如下:基于Socket和基于DBus的服务可一次并行启动所有进程,无需任何额外的同步。基于激活的策略还能令我们进行延迟加载服务。 如果服务很少被用到,我们可以在第一次被访问时启动,而不是在启动过程中启动。
3.3、并行化文件系统任务
系统启动过程中,文件系统相关的活动是最耗时的,比如挂载文件系统,fsck,磁盘配额检查等。
Systemd 集成了 autofs 的实现,对于系统中的挂载点,比如/home,当系统启动的时候,systemd 为其创建一个临时的自动挂载点。在这个时刻/home 真正的挂载设备尚未启动好,真正的挂载操作还没有执行,文件系统检测也还没有完成。可是那些依赖该目录的进程已经可以并发启动,他们的 open()操作被内建在 systemd 中的 autofs 捕获,将该 open()调用挂起(可中断睡眠状态)。然后等待真正的挂载操作完成,文件系统检测也完成后,systemd 将该自动挂载点替换为真正的挂载点,并让 open()调用返回。由此,实现了那些依赖于文件系统的服务和文件系统本身同时并发启动。
3.3.1、三个init启动时间示意图
3.3.2、systemd设置运行级别:
systemd执行的第一个目标是default.target
获取当前的运行级别:systemctl get-default
设置:systemctl set-default multi-user.target
/lib/systemd/system/default.target -> graphical.target
3.3.3、systemd与sysvinit运行级别对应表