操作系统启动的第一个进程
1、System V unix的init
我们在操作系统启动流程章节了解到了,当内核进入内存并挂载了根文件系统后会启动第一个Linux进程,这第一个Linux进程将会负责后续的Linux系统启动,这第一个启动的Linux进程将会负责其他的守护进程启动(服务),直到所有需要启动的守护进程都启动完毕(服务),至此操作系统算是加载完成了。通过上面的内容,我们了解到,这第一个守护进程在操作系统启动过程中是非常重要的一个进程,如果没有它,那linux操作系统将无法正常运行。Linux操作系统从诞生之初到现在已经接近40年了,Linux起初借鉴了System V unix的设计思路,采用了和System V unix同样的架构,使用Init作为第一个运行的进程(System V Init),就这样运行了20多年,后面因为一些原因改成了upstart,后面又因为一些原因,采用了Systemd。现在大部分新发布的Linux都几乎采用Systemd作为第一个启动的进程,用Init作为第一个启动进程的Linux发行版本几乎淘汰了,即使搭载upstart的Init现在也很少在新发布的linux系统中被采用了。掌握一门技术,知道其发展历程是非常重要的,知其然,然后知其所以然。想到够达到"然"和"所以然"的双知,需要了解整个发展历程。就像我们小时候做诗词鉴赏的时候,需要了解诗人的写作背景一样。切入主题,了解Linux系统的发展历程,能够更好的了解系统,掌握系统。我们现在学习Init有两个价值,第一个价值,通过Init的学习,当我们遇到一些比较旧的使用Init作为第一个启动进程的Linux发行版本我们也会使用Init的方式来管理服务。第二个价值就是,通过Init的学习,我们能知道Systemd的各方面比Init强大的优势。#System V Init(简称sysV Init)介绍1982 年左右 AT&T 基于原来的 UNIX7 版本开发了 UNIX System III 后来基于多方的经验在 1983 开发了 System V Release 1。这个 System V 就是一个版本的UNIX名称,其中 System V 的初始化程序就是 Systemvinit。早期的 Linux 发行版本采取的是 SystemV init 的初始化程序,少量发行版本使用 FreeBSD 的初始化程序。Linux采用了sysV Init思想的启动设计,内核初始化的最后一步就是启动pid为1的init进程,这个进程是系统的第一个进程,它负责启动所有其他操作系统加载所必须得进程。init以守护进程方式存在,是所有其他进程的祖先。init进程非常独特,能够完成其他进程所完成不了的任务。Init系统能够定义、管理、控制Init进程的行为。它负责组织和运行许多独立的或相关的始化工作(因此被称为 init 系统),从而让计算机系统进入某种用户预订的运行模式。仅仅将内核运行起来是毫无实际用途的,必须由 init 系统将系统代入可操作状态。比如启动外壳 shell 后,便有了人机交互,这样就可以让计算机执行一些预订程序完成有实际意义的任务。或者启动 X 图形系统以便提供更佳的人机界面,更加高效的完成任务。这里,字符界面的 shell 或者 X 系统都是一种预设的运行模式。大多数 Linux 发行版的 init 系统是和 System V 相兼容的,被称为 sysvinit。这是人们最熟悉的 init 系统。一些发行版如 Slackware 采用的是 BSD 风格 Init 系统,这种风格使用较少。Ubuntu 和 RHEL 采用 upstart 替代了传统的 sysvinit。而 Fedora 从版本 15 开始使用了一个被称为 systemd 的新 init 系统。在 Linux 主要应用于服务器和 PC 机的时代,SysVinit 运行非常良好,概念简单清晰。它主要依赖于 Shell 脚本,这就决定了它的最大弱点:启动太慢。在很少重新启动的 Server 上,这个缺点并不重要。而当 Linux 被应用到移动终端设备的时候,启动慢就成了一个大问题。为了更快地启动,人们开始改进 sysvinit,先后出现了 upstart 和 systemd 这两个主要的新一代 init 系统。Upstart 已经开发了很多年,在不少系统中已经替换 sysvinit。Systemd 出现较晚,但发展更快,大有取代 upstart 的趋势。

#sysvinit运行顺序Sysvinit 巧妙地用脚本,文件命名规则和软链接来实现不同的 runlevel。首先,sysvinit 需要读取/etc/inittab 文件。分析这个文件的内容,它获得以下一些配置信息:系统需要进入的 runlevel捕获组合键的定义定义电源 fail/restore 脚本启动 getty 和虚拟控制台得到配置信息后,sysvinit 顺序地执行以下这些步骤,从而将系统初始化为预订的 runlevel X。/etc/rc.d/rc.sysinit/etc/rc.d/rc 和/etc/rc.d/rcX.d/(X 代表运行级别 0-6)/etc/rc.d/rc.localX Display Manager(如果需要的话)首先,运行 rc.sysinit 以便执行一些重要的系统初始化任务。在 RedHat 公司的 RHEL5 中(RHEL6 已经使用 upstart了),rc.sysinit 主要完成以下这些工作。激活 udev 和 selinux设置定义在/etc/sysctl.conf 中的内核参数设置系统时钟加载 keymaps使能交换分区设置主机名(hostname)根分区检查和 remount激活 RAID 和 LVM 设备开启磁盘配额检查并挂载所有文件系统清除过期的 locks 和 PID 文件完成了以上这些工作之后,sysvinit 开始运行/etc/rc.d/rc 脚本。根据不同的 runlevel,rc 脚本将打开对应该 runlevel 的 rcX.d 目录(X 就是 runlevel),找到并运行存放在该目录下的所有启动脚本。每个 runlevel X 都有一个这样的目录,目录名为/etc/rc.d/rcX.d。在这些目录下存放着很多不同的脚本。文件名以 S 开头的脚本就是启动时应该运行的脚本,S 后面跟的数字定义了这些脚本的执行顺序。在/etc/rc.d/rcX.d 目录下的脚本其实都是一些软链接文件,真实的脚本文件存放在/etc/init.d 目录下。当所有的初始化脚本执行完毕。Sysvinit 运行/etc/rc.d/rc.local 脚本。从这里读取用户的个性化设置(用户自定义开机启动的项目)。#Sysvinit和系统关闭Sysvinit 不仅需要负责初始化系统,还需要负责关闭系统。在系统关闭时,为了保证数据的一致性,需要小心地按顺序进行结束和清理工作。比如应该先停止对文件系统有读写操作的服务,然后再卸载(umount)文件系统。否则数据就会丢失。这种顺序的控制这也是依靠/etc/rc.d/rcX.d/目录下所有脚本的命名规则来控制的,在该目录下所有以 K 开头的脚本都将在关闭系统时调用,字母 K 之后的数字定义了它们的执行顺序。 这些脚本负责安全地停止服务或者其他的关闭工作。#Sysvinit的管理和控制功能此外,在系统启动之后,管理员还需要对已经启动的进程进行管理和控制。原始的 sysvinit 软件包包含了一系列的控制启动,运行和关闭所有其他程序的工具。halt 停止系统。init 用此来切换系统的运行级别。killall5 向所有的进程发送信号。last 显示自从这个文件建立以来,所有用户的登录情况。lastb 作用和 last 差不多,默认情况下使用/var/log/btmp 文件,显示所有失败登录企图。mesg 控制其它用户对用户终端的访问。pidof 找出程序的pidpoweroff 关闭系统reboot 重启系统runlevel 读取系统的登录记录文件。shutdownsulogin 当系统进入当用户模式的时候,被init调用。utmpdump向标准输出设备输出/var/run/utmp文件的内容。wall向所有信息权限的登录用户发送信息。不同的 Linux 发行版在这些 sysvinit 的基本工具基础上又开发了一些辅助工具用来简化 init 系统的管理工作。比如RedHat 的 RHEL 在 sysvinit 的基础上开发了 initscripts 软件包,包含了大量的启动脚本(如 rc.sysinit),还提供了 service,chkconfig 等命令行工具,甚至一套图形化界面来管理 init 系统。其他的 Linux 发行版也有各自的 initscript 或其他名字的 init 软件包来简化 sysvinit 的管理。只要你理解了 sysvinit 的机制,在一个最简的仅有 sysvinit 的系统下,你也可以直接调用脚本启动和停止服务,手动创建 inittab 和创建软连接来完成这些任务。因此理解 sysvinit 的基本原理和命令是最重要的。你甚至也可以开发自己的一套管理工具。#Sysvinit总结Sysvinit 的优点是概念简单。Service 开发人员只需要编写启动和停止脚本,概念非常清楚;将 service 添加/删除到某个 runlevel 时,只需要执行一些创建/删除软连接文件的基本操作;这些都不需要学习额外的知识或特殊的定义语法(UpStart 和 Systemd 都需要用户学习新的定义系统初始化行为的语言)。其次,sysvinit 的另一个重要优点是确定的执行顺序:脚本严格按照启动数字的大小顺序执行,一个执行完毕再执行下一个,这非常有益于错误排查。UpStart 和 systemd 支持并发启动,导致没有人可以确定地了解具体的启动顺序,排错不易。但是串行地执行脚本导致 sysvinit 运行效率较慢,在新的 IT 环境下,启动快慢成为一个重要问题。此外动态设备加载等 Linux 新特性也暴露出 sysvinit 设计的一些问题。针对这些问题,人们开始想办法改进 sysvinit,以便加快启动时间,并解决 sysvinit 自身的设计问题。
2、upstat
Ubuntu从8.10开始,你会发现在你的操作系统上找不到/etc/inittab 文件了,这是因为 Ubuntu 使用了一种被称为 upstart 的新型 init 系统。Ubuntu 8.10 (Intrepid Ibex):首次引入 Upstart,但 SysVinit 仍作为备选。Ubuntu 9.04 (Jaunty Jackalope):Upstart 成为默认初始化系统,但保留了 SysVinit 兼容层。Ubuntu 9.10 (Karmic Koala):完全移除 SysVinit 相关脚本,全面转向 Upstart。Ubuntu 10.04 LTS (Lucid Lynx)至 Ubuntu 14.04 LTS (Trusty Tahr):长期支持版本均使用 Upstart。Ubuntu 15.04 (Vivid Vervet):开始使用 systemd 替代 Upstart,作为默认初始化系统。Ubuntu 16.04 LTS (Xenial Xerus)及后续版本:完全采用 systemd,不再支持 Upstart。大约在 2006 年或者更早的时候, Ubuntu 开发人员试图将 Linux 安装在笔记本电脑上。在这期间技术人员发现经典的 sysvinit 存在一些问题:它不适合笔记本环境。这促使程序员 Scott James Remnant 着手开发 upstart。当 Linux 内核进入 2.6 时代时,内核功能有了很多新的更新。新特性使得 Linux 不仅是一款优秀的服务器操作系统,也可以被用于桌面系统,甚至嵌入式设备。桌面系统或便携式设备的一个特点是经常重启,而且要频繁地使用硬件热插拔技术。在现代计算机系统中,硬件繁多、接口有限,人们并非将所有设备都始终连接在计算机上,比如 U 盘平时并不连接电脑,使用时才插入 USB 插口。因此,当系统上电启动时,一些外设可能并没有连接。而是在启动后当需要的时候才连接这些设备。在 2.6 内核支持下,一旦新外设连接到系统,内核便可以自动实时地发现它们,并初始化这些设备,进而使用它们。这为便携式设备用户提供了很大的灵活性。可是这些特性为 sysvinit 带来了一些挑战。当系统初始化时,需要被初始化的设备并没有连接到系统上;比如打印机。为了管理打印任务,系统需要启动 CUPS 等服务,而如果打印机没有接入系统的情况下,启动这些服务就是一种浪费。Sysvinit 没有办法处理这类需求,它必须一次性把所有可能用到的服务都启动起来,即使打印机并没有连接到系统,CUPS 服务也必须启动。还有网络共享盘的挂载问题。在/etc/fstab 中,可以指定系统自动挂载一个网络盘,比如 NFS,或者 iSCSI 设备。在本文的第一部分 sysvinit 的简介中可以看到,sysvinit 分析/etc/fstab 挂载文件系统这个步骤是在网络启动之前。可是如果网络没有启动,NFS 或者 iSCSI 都不可访问,当然也无法进行挂载操作。Sysvinit 采用 netdev 的方式来解决这个问题,即/etc/fstab 发现 netdev 属性挂载点的时候,不尝试挂载它,在网络初始化并使能之后,还有一个专门的 netfs 服务来挂载所有这些网络盘。这是一个不得已的补救方法,给管理员带来不便。部分新手管理员甚至从来也没有听说过 netdev 选项,因此经常成为系统管理的一个陷阱。针对以上种种情况,Ubuntu 开发人员在评估了当时的几个可选 init 系统之后,决定重新设计和开发一个全新的 init 系统,即 UpStart。UpStart 基于事件机制,比如 U 盘插入 USB 接口后,udev 得到内核通知,发现该设备,这就是一个新的事件。UpStart 在感知到该事件之后触发相应的等待任务,比如处理/etc/fstab 中存在的挂载点。采用这种事件驱动的模式,upstart 完美地解决了即插即用设备带来的新问题。此外,采用事件驱动机制也带来了一些其它有益的变化,比如加快了系统启动时间。sysvinit 运行时是同步阻塞的。一个脚本运行的时候,后续脚本必须等待。这意味着所有的初始化步骤都是串行执行的,而实际上很多服务彼此并不相关,完全可以并行启动,从而减小系统的启动时间。在 Linux 大量应用于服务器的时代,系统启动时间也许还不那么重要;然而对于桌面系统和便携式设备,启动时间的长短对用户体验影响很大。此外云计算等新的 Server 端技术也往往需要单个设备可以更加快速地启动。可以看到,UpStart 的设计比 SysVInit 更加先进。多数 Linux 发行版上已经不再使用 SysVInit,一部分发行版采用了UpStart,比如 Ubuntu;而另外一些比如 Fedora,采用了一种被称为 systemd 的 init 系统。Systemd 出现的比UpStart 更晚,但发展迅速,虽然 UpStart 也还在积极开发并被越来越多地应用,但 systemd 似乎发展更快.UpStart 满足了这些需求后,不仅桌面系统 Ubuntu 采用了 UpStart,甚至企业级服务器级的 RHEL 也默认采用 UpStart 来替换 sysvinit 作为 init 系统。

#Upstart 的特点UpStart 解决了之前提到的 sysvinit 的缺点。采用事件驱动模型,UpStart 可以:更快地启动系统当新硬件被发现时动态启动服务硬件被拔除时动态停止服务这些特点使得 UpStart 可以很好地应用在桌面或者便携式系统中,处理这些系统中的动态硬件插拔特性。#Upstart并行启动进程假设有 7 个不同的启动项目,比如 JobA、Job B 等等。在 SysVInit 中,每一个启动项目都由一个独立的脚本负责,它们由 sysVinit 顺序地,串行地调用。因此总的启动时间为 T1+T2+T3+T4+T5+T6+T7。其中一些任务有依赖关系,比如A,B,C,D。而 Job E 和 F 却和 A,B,C,D 无关。这种情况下,UpStart 能够并发地运行任务{E,F,(A,B,C,D)},使得总的启动时间减少为 T1+T2+T3。这无疑增加了系统启动的并行性,从而提高了系统启动速度。但是在 UpStart 中,有依赖关系的服务还是必须先后启动。比如任务 A,B,(C,D)因为存在依赖关系,所以在这个局部,还是串行执行。#Upstart概念和术语Upstart 的基本概念和设计清晰明确。UpStart 主要的概念是 job 和 event。Job 就是一个工作单元,用来完成一件工作,比如启动一个后台服务,或者运行一个配置命令。每个 Job 都等待一个或多个事件,一旦事件发生,upstart 就触发该 job 完成相应的工作。1.JobJob 就是一个工作的单元,一个任务或者一个服务。可以理解为 sysvinit 中的一个服务脚本。有三种类型的工作:task job;service job;abstract job;task job 代表在一定时间内会执行完毕的任务,比如删除一个文件;service job 代表后台服务进程,比如 apache httpd。这里进程一般不会退出,一旦开始运行就成为一个后台守护进程,由 init 进程管理,如果这类进程退出,由 init 进程重新启动,它们只能由 init 进程发送信号停止。它们的停止一般也是由于所依赖的停止事件而触发的,不过 upstart 也提供命令行工具,让管理人员手动停止某个服务;Abstract job 仅由 upstart 内部使用,仅对理解 upstart 内部机理有所帮助。我们不用关心它。除了以上的分类之外,还有另一种工作(Job)分类方法。Upstart 不仅可以用来为整个系统的初始化服务,也可以为每个用户会话(session)的初始化服务。系统的初始化任务就叫做 system job,比如挂载文件系统的任务就是一个 system job;用户会话的初始化服务就叫做 session job。2.事件 Event顾名思义,Event 就是一个事件。事件在 upstart 中以通知消息的形式具体存在。一旦某个事件发生了,Upstart 就向整个系统发送一个消息。没有任何手段阻止事件消息被 upstart 的其它部分知晓,也就是说,事件一旦发生,整个 upstart 系统中所有工作和其它的事件都会得到通知。下面是一些常见的事件:系统上电启动,init 进程会发送"start"事件根文件系统可写时,相应 job 会发送文件系统就绪的事件一个块设备被发现并初始化完成,发送相应的事件某个文件系统被挂载,发送相应的事件类似 atd 和 cron,可以在某个时间点,或者周期的时间点发送事件另外一个 job 开始或结束时,发送相应的事件一个磁盘文件被修改时,可以发出相应的事件一个网络设备被发现时,可以发出相应的事件缺省路由被添加或删除时,可以发出相应的事件不同的 Linux 发行版对 upstart 有不同的定制和实现,实现和支持的事件也有所不同,可以用`man 7 upstart-events`来查看事件列表。#Job 和 Event 的相互协作Upstart 就是由事件触发工作运行的一个系统,每一个程序的运行都由其依赖的事件发生而触发的。系统初始化的过程是在工作和事件的相互协作下完成的,可以大致描述如下:系统初始化时,init 进程开始运行,init 进程自身会发出不同的事件,这些最初的事件会触发一些工作运行。每个工作运行过程中会释放不同的事件,这些事件又将触发新的工作运行。如此反复,直到整个系统正常运行起来。#Upstart 小结UpStart 的设计比 SysVInit 更加先进。upstart 通过并行启动加快执行速度,它对于相互依赖的服务采用并发启动。它也支持硬件热插拔时的动态启动和卸载。多数 Linux 发行版上已经不再使用 SysVInit,一部分发行版采用了 UpStart,比如 Ubuntu;而另外一些比如 Fedora,采用了一种被称为 systemd 的 init 系统。Systemd 出现的比 UpStart 更晚,但发展迅速,虽然 UpStart 也还在积极开发并被越来越多地应用,但 systemd 发展更快.
3、systemd的设计
3.1systemd介绍
2010年,在红帽公司工作的Lennart Poettering和Kay Sievers发起了开发systemd的项目,旨在取代Linux的传统System V init。Lennart Poettering希望通过systemd提供更优秀的框架来表示系统服务间的依赖关系,实现系统初始化时服务的并行启动,降低Shell的系统开销。2010 年 4 月,Poettering 发表了一篇题为“重新思考 PID 1”的博客文章,这个介绍后来成为 systemd 的实验版本。2011 年 5 月,Fedora Linux 成为第一个默认启用 systemd 的主要 Linux 发行版。此后,越来越多的 Linux 发行版开始采用 systemd,逐渐取代了其他 init 系统,而且 systemd 在与当时最主流的 init 系统 upstart 的竞争中胜出。systemd是linux系统中最新的初始化系统(init),它主要的设计目标是克服sysvinit固有的缺点,提高系统的启动速度。systemd和ubuntu的upstart是竞争对手,但是时至今日ubuntu也采用了systemd,所以systemd在竞争中胜出,大有一统天下的趋势。其实,systemd的很多概念都来源于苹果Mac OS操作系统上的launchd(mac OS的初始化系统),开发者 Lennart Poettering 在设计 systemd 时,公开提及参考了 launchd 的部分理念(如并行启动、基于依赖关系的服务管理、统一配置文件格式)。systemd的优点是功能强大,使用方便,缺点是体系庞大,非常复杂,下图展示了systemd的架构

3.2systemd兼容性
Systemd是一个"新来的"操作系统初始化方案,Linux上的很多应用程序并没有来得及为它做相应的改变。systemd引入了新的配置方式,对应用程序的开发也有一些新的要求。如果 systemd 想替代目前正在运行的初始化系统,就必须和现有程序兼容。任何一个 Linux 发行版都很难为了采用 systemd 而在短时间内将所有的服务代码都修改一遍。Systemd 提供了和 Sysvinit兼容的特性。系统中已经存在的服务和进程无需修改。这降低了系统向 systemd 迁移的成本,使得 systemd 替换现有初始化系统成为可能。systemd-sysv-generator能动态将 /etc/init.d/ 目录下的 SysV 脚本转换为临时 systemd 单元systemd-upstart-generator尝试将 /etc/init/ 目录下的 upstart.conf 文件转换为 systemd 单元。systemd 的兼容机制为旧系统迁移提供了缓冲,但长期建议使用原生 systemd 单元以获得最佳性能和完整功能。通过自动转换工具、命令兼容层和渐进式迁移策略,systemd 成功平衡了向前演进与向后兼容的矛盾,成为现代 Linux 系统的主流初始化方案。
3.3systemd启动速度
#systemd启动速度systemd 提供了比 upstart 更激进的并行启动能力,采用了socket / D-Bus activation等技术启动服务。一个显而易见的结果就是:更快的启动速度。为了减少系统启动时间,systemd 的目标是:尽可能启动更少的进程尽可能将更多进程并行启动同样地,upstart 也试图实现这两个目标。下图展示了 upstart 相对于 sysvinit 在并发启动这个方面的改进

upstart 增加了系统启动的并行性,从而提高了系统启动速度。但是在 upstart 中,有依赖关系的服务还是必须先后启动。比如任务 1,2,(3,4)因为存在依赖关系,所以在这个局部,还是串行执行。systemd 能够更进一步提高并发性,即便对于那些 upstart 认为存在相互依赖而必须串行的服务,systemd也可以并发启动。在 systemd 中,所有的任务都同时并发执行,总的启动时间被进一步降低为 T1。可见 systemd 比 upstart 更进一步提高了并行启动能力,极大地加速了系统启动时间。
3.4systemd按需启动能力
#systemd提供按需启动能力当 sysvinit 系统初始化的时候,它会将所有可能用到的后台服务进程全部启动运行。并且系统必须等待所有的服务都启动就绪之后,才允许用户登录。这种做法有两个缺点:首先是启动时间过长,其次是系统资源浪费。使用了systemd,你会发现系统好像已经加载了登录界面,但是你无法登录,这是因为控制登录的进程已经启动了,但是其他的进程还没有就绪,就导致了你看着登录界面已经加载出来了,但是实际上无法登录的情况,这是采用systemd之后很普遍的一个现象,不要意外,这样做的好处就是你的用户登录进程不再需要其他进程启动后才开始启动,因为一步慢,步步慢。某些服务很可能在很长一段时间内,甚至整个服务器运行期间都没有被使用过。比如 CUPS,打印服务在多数服务器上很少被真正使用到。你可能没有想到,在很多服务器上 SSHD 也是很少被真正访问到的。花费在启动这些服务上的时间是不必要的;同样,花费在这些服务上的系统资源也是一种浪费。systemd 可以提供按需启动的能力,只有在某个服务被真正请求的时候才启动它。当该服务结束,systemd可以关闭它,等待下次需要时再次启动它。这有点类似于以前系统中的 xinetd。#xinetd介绍xinetd(Extended Internet Services Daemon)是 Linux 系统中用于管理和提供网络服务的守护进程,它是传统 inetd(Internet Services Daemon)的增强版本。xinetd 主要负责监听网络请求,并根据请求类型动态启动相应的服务进程,这种机制被称为 "超级服务器"(super-server)。1.按需启动服务xinetd 监听指定端口,当有客户端请求到达时,才动态启动对应的服务进程。这种设计减少了常驻进程数量,降低系统资源消耗。2.增强的安全性提供访问控制功能,可基于 IP 地址、网络、时间等条件限制服务访问。支持 TCP Wrappers,进一步增强网络服务的安全性。具备服务速率限制,防止 DoS 攻击。3.配置灵活通过独立的配置文件(通常位于/etc/xinetd.d/目录下)管理每个服务,配置项丰富且易于理解。4.日志记录可详细记录服务的连接信息和状态,便于系统监控和审计。5.工作原理xinetd 在系统启动时启动,监听所有配置的服务端口。当客户端连接到某个端口时,xinetd 接收连接请求。根据配置文件,xinetd 启动对应的服务进程,并将客户端连接传递给该进程。服务进程处理完请求后退出,资源被系统回收。6.典型应用场景管理轻量级网络服务(如 telnet、ftp、tftp 等)。为不支持独立守护进程的服务提供后台运行能力。集中管理和监控多个网络服务。7.配置示例以下是一个 xinetd 配置文件(例如/etc/xinetd.d/telnet)的示例:service telnet{disable = no# 是否禁用该服务socket_type = stream# 套接字类型protocol = tcp# 协议类型wait = no# 是否等待服务结束user = root# 运行服务的用户server = /usr/sbin/in.telnetd# 服务程序路径log_on_failure += USERID# 失败时记录用户信息only_from = 192.168.1.0/24# 允许访问的IP范围}8.与systemd的关系随着 Linux 系统逐渐采用 systemd 作为初始化系统,xinetd 的使用场景有所减少。systemd 提供了类似的套接字激活机制(socket activation),可替代xinetd的部分功能。然而,在一些传统环境或特定需求下,xinetd仍然被广泛使用。#systemd的按需启动核心原理1.socket激活(最核心的按需启动机制)通过监听 socket(如 TCP/UDP 端口、Unix 域套接字),仅当有客户端连接时才触发对应服务的启动,避免服务提前驻留内存。systemd 内置 socket 守护进程(如 systemd-socketd)统一管理所有监听 socket。2.D-Bus激活(针对桌面服务)通过监听 D-Bus 接口触发服务启动,典型场景是当桌面环境中的打印服务(cups-browsed.service)仅在需要访问时启动。3.Path激活监控文件或目录变化(如写入新文件)时启动服务,适用于日志处理、文件同步等场景。4.Timer激活通过 .timer 单元实现周期性按需启动,替代传统 cron 任务。5.Device激活当 USB 设备、硬盘分区等接入时启动对应服务(如文件系统挂载、驱动加载)
3.5cgroups管理进程的生命周期
#采用linux 的 cgroups 跟踪和管理进程的生命周期systemd 利用了 Linux 内核的特性即 cgroups 来完成跟踪的任务。当停止服务时,通过查询 cgroups,systemd 可以确保找到所有的相关进程,从而干净地停止服务。cgroups 已经出现了很久,它主要用来实现系统资源配额管理。cgroups 提供了类似文件系统的接口,使用方便。当进程创建子进程时,子进程会继承父进程的 cgroups。因此无论服务如何启动新的子进程,所有的这些相关进程都会属于同一个 cgroups,systemd只需要简单地遍历指定的cgroups即可正确地找到所有的相关进程,将它们一一停止即可。


3.6启动挂载点和自动挂载
#启动挂载点和自动挂载的管理传统的 linux 系统中,用户可以用 /etc/fstab 文件来维护固定的文件系统挂载点。这些挂载点在系统启动过程中被自动挂载,一旦启动过程结束,这些挂载点就会确保存在。这些挂载点都是对系统运行至关重要的文件系统,比如 HOME 目录。和 sysvinit 一样,Systemd 管理这些挂载点,以便能够在系统启动时自动挂载它们。systemd 还兼容 /etc/fstab 文件,你可以继续使用该文件管理挂载点。有时候用户还需要动态挂载点,比如打算访问 DVD 或者 NFS 共享的内容时,才临时执行挂载以便访问其中的内容,而不访问光盘时该挂载点被取消(umount),以便节约资源。传统地,人们依赖 autofs 服务来实现这种功能。systemd 内建了自动挂载服务,无需另外安装 autofs 服务,可以直接使用 systemd 提供的自动挂载管理能力来实现 autofs 的功能。
3.7systemd处理依赖关系
#systemd处理依赖关系系统启动过程是由很多的独立工作共同组成的,这些工作之间可能存在依赖关系,比如挂载一个 NFS 文件系统必须依赖网络能够正常工作。systemd 虽然能够最大限度地并发执行很多有依赖关系的工作,但是类似"挂载 NFS"和"启动网络"这样的工作还是存在天生的先后依赖关系,无法并发执行。所以你会发现,有时候操作系统启动了,你已经登录了操作系统,但是你明明定义了nfs-server开机启动,但是等了一段时间,你还没有发现nfs-server启动,过了一段时间再检查nfs-server,就发现nfs-server已经启动了。#依赖关系介绍https://www.jinbuguo.com/systemd/systemd.unit.htmlsystemd 通过 单元文件(Unit Files) 和 依赖关系图(Dependency Graph) 实现高效的服务管理,其依赖处理机制是核心优势之一。1.Requires2.Requisite3.Wants4.BindsTo5.PartOf6.Conflicts7.Before和After
3.8systemd日志服务
#日志服务 systemd 自带日志服务 journald,该日志服务的设计初衷是克服现有的 syslog 服务的缺点。比如: syslog 不安全,消息的内容无法验证。每一个本地进程都可以声称自己是 Apache PID 4711,而 syslog 也就相信并保存到磁盘上。 数据没有严格的格式,非常随意。自动化的日志分析器需要分析人类语言字符串来识别消息。一方面此类分析困难低效;此外日志格式的变化会导致分析代码需要更新甚至重写。 systemd journal 用二进制格式保存所有日志信息,用户使用 journalctl 命令来查看日志信息。无需自己编写复杂脆弱的字符串分析处理程序。 Systemd的字母d是守护进程(daemon)的缩写。Systemd这个名字的含义,就是它要守护整个系统。