初始化到底是做什么的?


43

我正在创建一个Linux发行版,现在我需要一个初始化程序。我可以很好地用c编写代码,并且我对linux相当了解(虽然不多,但是我使用arch linux进行开发已有4年了),所以我认为我应该尝试用C编写自己的基本初始化脚本。只是想知道,init会执行哪些任务来为简单的shell设置系统?(当我问“ init有什么作用?”时,我确实知道init是什么,它有什么用。我只是不知道它有什么任务。)

我不需要代码,甚至可能不需要基本命令,但是我确实需要它们的运行顺序。


1
您可以对SysV风格的初始化脚本使用任何喜欢的解释器,包括Perl,awk,bash,(t)csh,本机二进制文件,...通常使用Bash,因为实际上保证可以在此类脚本所在的系统上使用Bash。部署在引导过程中的相关时间点,并不是因为SysVinit和bash之间存在某种耦合。SysVinit定义了合同,每个脚本都可以自由地以其开发人员认为合适的方式来实现该合同。
CVn

Answers:


53

系统5 init只会告诉您故事的一小部分。

有一种影响Linux世界的近视眼。人们认为他们使用的是称为“ System 5 init” 的东西,这既是传统的东西,也是最好的起点。事实并非如此。

对于初学者来说,传统实际上并不是人们所说的那样。System 5 init和System 5可以rc追溯到AT&T UNIX System 5,它在第一个UNIX之后几乎与我们现在(说)在Linux-Mandrake的第一个版本之后一样远。

1st Edition只有UNIX init。它没有rc。第一版汇编语言init其代码已由Warren Toomey等人还原并提供)直接产生并重新产生12个getty进程,从内置表中装入3个硬连线的文件系统,并直接从程序的主目录运行程序用户名为mel。该getty表也​​直接在程序映像中。

在UNIX System 5之后又十年,所谓的“传统” Linux init系统出现了。1992年,Miquel van Smoorenburg(重新)编写了Linux init+ rc及其相关工具,人们现在将其称为“ System 5 init”,即使它实际上不是UNIX System 5中的软件(并且不仅仅是init)。

System 5 init/ rc并不是最好的起点,即使有人增加了对systemd的了解,但它覆盖的知识不足一半。仅在过去的二十年里,在init系统设计(针对Linux和BSD)方面已经进行了很多工作。已经讨论,制定,设计,实施和实践了各种工程决策。商业大学也做了很多。

现有的系统来学习和学习

这是这两个系统以外的一些主要初始化系统及其(几个)显着点中的一两个的不完整列表:

  • 约阿希姆·尼尔森(Joachim Nilsson)的finit走上了使用更易理解的配置文件的路线。
  • Felix von Leitner的minit用于文件系统即数据库配置系统,较小的内存占用空间以及启动之间的启动/停止依赖关系init
  • Gerrit Pape的runit遵循了我先前所描述的刚刚生成的四个shell脚本方法。
  • InitNG的目标是具有依赖项,命名目标,多个配置文件以及更灵活的配置语法,整个子进程会加载更多设置。
  • 新贵进行了全面的重新设计,将系统完全不建模为服务和相互依赖性,而是将其建模为事件和作业触发的事件。
  • nosh的设计包括将所有服务管理(甚至包括生成getty和僵尸收获)推送到单独的服务管理器中,并且处理特定于操作系统的“ API”设备/符号链接/目录和系统事件。
  • sinit是一个非常简单的初始化。它执行/bin/rc.init的任务是启动程序,挂载文件系统等。为此,您可以使用诸如minirc之类的东西

此外,大约10年前,daemontools用户和其他人之间进行了讨论,将其svscan用作流程#1,这引发了诸如Paul Jarc的svscan作为流程1研究Gerrit Pape的想法以及Laurent Bercot的svscan作为流程1之类的项目

这使我们进入了#1程序执行的过程。

#1程序执行什么处理

关于“应该”执行哪个处理#1的概念,从本质上讲是主观的。一个有意义的客观设计准则是至少#1流程必须执行的操作。内核对此施加了一些要求。而且总是有一些特定于操作系统的事情要做。当谈到传统上#1所完成的过程时,我们并没有达到最低要求,也从未真正做到过。

进程#1的各种操作系统内核和其他程序需要做一些事情,而这些事情是无法逃避的。

人们会告诉你,fork()做事并充当孤立流程的父代是流程#1的主要功能。具有讽刺意味的是,这是不正确的。处理孤立进程(使用最新的Linux内核,如https://unix.stackexchange.com/a/177361/5132所述)是该系统的一部分,可以使进程#1很大程度上脱离其他进程,例如专门的服务经理。所有这些都是服务管理器,它们用尽了流程#1:

  • IBM AIX srcmstr程序,系统资源控制器
  • Gerrit Pape runsvdir来自runit
  • 丹尼尔J. Bernstein的svscan来自daemontools的,亚当·桑普森的svscanfreedt,布鲁斯·冈特的svscan距离的daemontools-安可,和Laurent Bercot的s6-svscan从S6
  • 韦恩·马歇尔(Wayne Marshall)的perpd演员
  • Solaris 10中的服务管理工具
  • service-manager从NOSH

类似地,如https://superuser.com/a/888936/38062所述,整个/dev/initctl想法不必位于流程#1附近。具有讽刺意味的是,高度集中化的systemd证明它可以移出流程#1。

相反,对于强制性的东西init,人们通常是在现成的,顶级的头他们的设计忘记,是东西,如搬运SIGINTSIGPWRSIGWINCH,等从内核发送并颁布发的各种系统状态的更改请求从“知道”某些信号到程序1的程序中就意味着某些事情。(例如:如https://unix.stackexchange.com/a/196471/5132所述,BSD工具集“知道” SIGUSR1具有特定含义。)

还有一些一次性的初始化和完成任务,这些任务无法逃脱,或者因不执行而遭受极大的痛苦,例如,安装“ API”文件系统或刷新文件系统缓存。

处理“ API”文件系统的基础与initrom 1st Edition UNIX 的操作没有什么不同:一个将一系列信息硬连线到程序中,而一个简单地mount()将列表中的所有条目都存储了下来。init通过nosh system-manager到systemd ,您会在BSD(sic!)等各种系统中找到这种机制。

“为简单的外壳设置系统”

如您init=/bin/sh所见,没有安装“ API”文件系统,在一种类型exithttps://unix.stackexchange.com/a/195978/5132)上以不费劲的方式崩溃,没有缓存刷新,并且通常将其保留(超级)用户可以手动执行使系统最低限度可用的操作。

要了解实际上除了在#1程序中要做的事情之外,别无选择,从而为您设定的目标设定好的路线,最好的选择是查看Gerrit Pape的runit,Felix von的操作上的重叠之处Leitner的minit和system-manager来自nosh包的程序。前两个显示了两个极简主义的尝试,但仍然处理了无法避免的问题。

我建议后者对于system-manager程序的大量手动输入很有用,它详细说明了已安装的“ API”文件系统,正在运行的初始化任务以及已处理的信号。在设计上具有系统管理器的系统中,它仅产生了其他三件事(服务管理器,附带的记录器以及用于运行状态更改的程序),并且仅在进程#1中不可避免地进行了操作。


3
很棒的答案,也很有帮助。但是我要问自己,OSX在这张大图上的位置launchd。有时人们会完全忘记OSX是* nix大家族的一员(很棒)。
DavAlPi 2015年

4

Debian上的System V init(还有其他变体和变体)执行以下操作:

  • 输入运行级别时,它将/etc/rcX.d/S*以字母数字顺序调用脚本,其中X运行级别为。这些脚本应设置运行级别。典型的设置是启动守护程序,并为该运行级别执行设置任务。进入运行级别时,这是一次性的事情。
  • 在运行级别中,它将启动列出的守护程序,该守护程序/etc/inittab需要在该运行级别期间处于活动状态。如果这些守护程序停止运行,它将重新启动它们。虽然您可以通过来管理任何守护进程init,但至少要输入几个守护进程getty才能登录。 getty登录完成后退出,然后init重新启动它,提供新的登录提示。
    • 如果守护程序在很短的时间内重新启动了太多次,它将停止尝试重新启动一段时间。
    • 仅仅因为某些事情是在进入运行级别时由启动脚本启动的,并不能init自动尝试使其保持运行状态。您需要在中单独指定/etc/inittab
  • 退出运行级别时,它将/etc/rcX.d/K*以字母数字顺序调用脚本,其中X运行级别为。实现关机或重新启动的一种方法是为这些事件定义一个运行级别,并使最后一个任务执行haltor reboot命令。
  • 它将响应某些事件(例如电源事件或Ctrl-Alt-Del)来调用可执行文件。
  • 它在套接字上侦听,如果收到某些消息,它将更改运行级别。

因此,init如果需要,您可以用作基本的服务管理器,但这几天的主要任务是使保持getty可用,以便用户可以登录并启动运行级别转换。

我只是想知道,init会执行哪些任务来为简单的shell设置系统?

无论你想要什么。在Debian上,每个/etc/rcX.d目录中都有一个脚本的符号链接/etc/init.d,您可以完全自定义或删除这些脚本。顺序由每个脚本与前面的建立0001

如果您只想生成一个shell,也可以指定一个-b选项init(即通过内核命令行)init。当您退出外壳initinit死亡时,内核会死机。


2

init必须要做的绝对最低限度的操作是至少运行另一个程序,并且永远不要退出。如果初始化退出,则系统崩溃。我想即使运行另一个程序也不是绝对必要的,但是如果您不这样做,则init必须负责完成系统预期要做的每件事,否则就没有太大用处。


1
我的Linux系统存在故障,PID 1崩溃了,但是系统基本上保持运行。PID 1崩溃的严重程度可能取决于内核版本。
吉尔斯(Gilles)'所以

1

init 可以做任何你想做的事

init是在引导过程结束时由Linux内核调用的任意可执行文件(也是唯一这样的可执行文件)。

通常将其实现为ELF可执行文件,但甚至可以是带有以下内容的Shell脚本chmod +xInit作为Shell脚本

像sysemd这样的典型实现将读取配置文件ofen /etc/initrc,然后基于这些配置派生一堆用户级进程,以实现系统的各个方面。

但是,这完全是特定于实现的,因此,如果不指定特定的实现,就无法回答您的问题。例如,我一直在玩一个init仅出于教育目的而进行reboot系统调用的过程。

Linux内核/init默认情况下只是在路径中查找可执行文件,但是init=Linux内核命令行参数可以覆盖此文件。

一种有效的解决方法init是使用QEMU,因为您可以使用该-append选项从QEMU命令行将内核命令行参数传递给QEMU ,而不必担心会阻塞桌面。

这是我的最低限度的全自动Buildroot + QEMU设置,它使您可以轻松地使用自己的init来揭开此事的神秘面纱。


0

如果您奉行模块化的“做一件事,做好事”的原则,那么init程序应该启动流程。

开始过程

一旦内核成功解压,就应执行该命令,并执行初始化系统所需的所有初始过程(例如,安装/ etc / fstab中的驱动器,打开网络接口以及依此类推)。

由于启动和关闭过程实际上是彼此相反的,因此,init程序通常还必须确保在关闭命令后停止进程。

停止流程

这意味着它必须根据该进程的手册页停止该进程(换句话说,不仅仅是公然的kill -9,它还应以希望结束的方式关闭该进程),卸载驱动器,并最终发出最终的掉电命令。

参考文献

关于其他人如何完成此操作的一个很好的参考是查看Slackware的/etc/rc.d脚本,以及已经存在的简单init系统,例如 ninit(minit的后继系统)。它具有流程监督(这意味着如果流程死亡,则将其重新启动),这可以说不是init的工作,但是它仍然是相当基本和易于理解的,尤其是通过作者的示例脚本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.