我正在创建一个Linux发行版,现在我需要一个初始化程序。我可以很好地用c编写代码,并且我对linux相当了解(虽然不多,但是我使用arch linux进行开发已有4年了),所以我认为我应该尝试用C编写自己的基本初始化脚本。只是想知道,init会执行哪些任务来为简单的shell设置系统?(当我问“ init有什么作用?”时,我确实知道init是什么,它有什么用。我只是不知道它有什么任务。)
我不需要代码,甚至可能不需要基本命令,但是我确实需要它们的运行顺序。
我正在创建一个Linux发行版,现在我需要一个初始化程序。我可以很好地用c编写代码,并且我对linux相当了解(虽然不多,但是我使用arch linux进行开发已有4年了),所以我认为我应该尝试用C编写自己的基本初始化脚本。只是想知道,init会执行哪些任务来为简单的shell设置系统?(当我问“ init有什么作用?”时,我确实知道init是什么,它有什么用。我只是不知道它有什么任务。)
我不需要代码,甚至可能不需要基本命令,但是我确实需要它们的运行顺序。
Answers:
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)方面已经进行了很多工作。已经讨论,制定,设计,实施和实践了各种工程决策。商业大学也做了很多。
这是除这两个系统以外的一些主要初始化系统及其(几个)显着点中的一两个的不完整列表:
init
。getty
和僵尸收获)推送到单独的服务管理器中,并且仅处理特定于操作系统的“ API”设备/符号链接/目录和系统事件。/bin/rc.init
的任务是启动程序,挂载文件系统等。为此,您可以使用诸如minirc之类的东西。此外,大约10年前,daemontools用户和其他人之间进行了讨论,将其svscan
用作流程#1,这引发了诸如Paul Jarc的svscan作为流程1研究,Gerrit Pape的想法以及Laurent Bercot的svscan作为流程1之类的项目。
这使我们进入了#1程序执行的过程。
关于“应该”执行哪个处理#1的概念,从本质上讲是主观的。一个有意义的客观设计准则是至少#1流程必须执行的操作。内核对此施加了一些要求。而且总是有一些特定于操作系统的事情要做。当谈到传统上#1所完成的过程时,我们并没有达到最低要求,也从未真正做到过。
进程#1的各种操作系统内核和其他程序需要做一些事情,而这些事情是无法逃避的。
人们会告诉你,fork()
做事并充当孤立流程的父代是流程#1的主要功能。具有讽刺意味的是,这是不正确的。处理孤立进程(使用最新的Linux内核,如https://unix.stackexchange.com/a/177361/5132所述)是该系统的一部分,可以使进程#1很大程度上脱离其他进程,例如专门的服务经理。所有这些都是服务管理器,它们用尽了流程#1:
srcmstr
程序,系统资源控制器runsvdir
来自runitsvscan
来自daemontools的,亚当·桑普森的svscan
从freedt,布鲁斯·冈特的svscan
距离的daemontools-安可,和Laurent Bercot的s6-svscan
从S6perpd
演员service-manager
从NOSH类似地,如https://superuser.com/a/888936/38062所述,整个/dev/initctl
想法不必位于流程#1附近。具有讽刺意味的是,高度集中化的systemd证明它可以移出流程#1。
相反,对于强制性的东西init
,人们通常是在现成的,顶级的头他们的设计忘记,是东西,如搬运SIGINT
,SIGPWR
,SIGWINCH
,等从内核发送并颁布发的各种系统状态的更改请求从“知道”某些信号到程序1的程序中就意味着某些事情。(例如:如https://unix.stackexchange.com/a/196471/5132所述,BSD工具集“知道” SIGUSR1
具有特定含义。)
还有一些一次性的初始化和完成任务,这些任务无法逃脱,或者因不执行而遭受极大的痛苦,例如,安装“ API”文件系统或刷新文件系统缓存。
处理“ API”文件系统的基础与init
rom 1st Edition UNIX 的操作没有什么不同:一个将一系列信息硬连线到程序中,而一个简单地mount()
将列表中的所有条目都存储了下来。init
通过nosh system-manager
到systemd ,您会在BSD(sic!)等各种系统中找到这种机制。
如您init=/bin/sh
所见,没有安装“ API”文件系统,在一种类型exit
(https://unix.stackexchange.com/a/195978/5132)上以不费劲的方式崩溃,没有缓存刷新,并且通常将其保留(超级)用户可以手动执行使系统最低限度可用的操作。
要了解实际上除了在#1程序中要做的事情之外,别无选择,从而为您设定的目标设定好的路线,最好的选择是查看Gerrit Pape的runit,Felix von的操作上的重叠之处Leitner的minit和system-manager
来自nosh包的程序。前两个显示了两个极简主义的尝试,但仍然处理了无法避免的问题。
我建议后者对于system-manager
程序的大量手动输入很有用,它详细说明了已安装的“ API”文件系统,正在运行的初始化任务以及已处理的信号。在设计上具有系统管理器的系统中,它仅产生了其他三件事(服务管理器,附带的记录器以及用于运行状态更改的程序),并且仅在进程#1中不可避免地进行了操作。
launchd
。有时人们会完全忘记OSX是* nix大家族的一员(很棒)。
Debian上的System V init(还有其他变体和变体)执行以下操作:
/etc/rcX.d/S*
以字母数字顺序调用脚本,其中X
运行级别为。这些脚本应设置运行级别。典型的设置是启动守护程序,并为该运行级别执行设置任务。进入运行级别时,这是一次性的事情。/etc/inittab
需要在该运行级别期间处于活动状态。如果这些守护程序停止运行,它将重新启动它们。虽然您可以通过来管理任何守护进程init
,但至少要输入几个守护进程getty
才能登录。 getty
登录完成后退出,然后init
重新启动它,提供新的登录提示。init
自动尝试使其保持运行状态。您需要在中单独指定/etc/inittab
。/etc/rcX.d/K*
以字母数字顺序调用脚本,其中X
运行级别为。实现关机或重新启动的一种方法是为这些事件定义一个运行级别,并使最后一个任务执行halt
or reboot
命令。因此,init
如果需要,您可以用作基本的服务管理器,但这几天的主要任务是使保持getty
可用,以便用户可以登录并启动运行级别转换。
我只是想知道,init会执行哪些任务来为简单的shell设置系统?
无论你想要什么。在Debian上,每个/etc/rcX.d
目录中都有一个脚本的符号链接/etc/init.d
,您可以完全自定义或删除这些脚本。顺序由每个脚本与前面的建立00
,01
等
如果您只想生成一个shell,也可以指定一个-b
选项init
(即通过内核命令行)init
。当您退出外壳init
并init
死亡时,内核会死机。
init必须要做的绝对最低限度的操作是至少运行另一个程序,并且永远不要退出。如果初始化退出,则系统崩溃。我想即使运行另一个程序也不是绝对必要的,但是如果您不这样做,则init必须负责完成系统预期要做的每件事,否则就没有太大用处。
init
可以做任何你想做的事
init是在引导过程结束时由Linux内核调用的任意可执行文件(也是唯一这样的可执行文件)。
通常将其实现为ELF可执行文件,但甚至可以是带有以下内容的Shell脚本chmod +x
:Init作为Shell脚本
像sysemd这样的典型实现将读取配置文件ofen /etc/initrc
,然后基于这些配置派生一堆用户级进程,以实现系统的各个方面。
但是,这完全是特定于实现的,因此,如果不指定特定的实现,就无法回答您的问题。例如,我一直在玩一个init
仅出于教育目的而进行reboot
系统调用的过程。
Linux内核/init
默认情况下只是在路径中查找可执行文件,但是init=
Linux内核命令行参数可以覆盖此文件。
一种有效的解决方法init
是使用QEMU,因为您可以使用该-append
选项从QEMU命令行将内核命令行参数传递给QEMU ,而不必担心会阻塞桌面。
这是我的最低限度的全自动Buildroot + QEMU设置,它使您可以轻松地使用自己的init来揭开此事的神秘面纱。
如果您奉行模块化的“做一件事,做好事”的原则,那么init
程序应该启动流程。
一旦内核成功解压,就应执行该命令,并执行初始化系统所需的所有初始过程(例如,安装/ etc / fstab中的驱动器,打开网络接口以及依此类推)。
由于启动和关闭过程实际上是彼此相反的,因此,init程序通常还必须确保在关闭命令后停止进程。
这意味着它必须根据该进程的手册页停止该进程(换句话说,不仅仅是公然的kill -9
,它还应以希望结束的方式关闭该进程),卸载驱动器,并最终发出最终的掉电命令。
关于其他人如何完成此操作的一个很好的参考是查看Slackware的/etc/rc.d脚本,以及已经存在的简单init系统,例如 ninit(minit的后继系统)。它具有流程监督(这意味着如果流程死亡,则将其重新启动),这可以说不是init的工作,但是它仍然是相当基本和易于理解的,尤其是通过作者的示例脚本。