UNIX init进程是否总是运行
Does the UNIX init process always run
我对 UNIX 中的 init 进程如何工作有疑问。据我了解,init 进程是第一个启动的,然后其他进程将其分叉。
假设我们启动 init 进程,然后派生一个子进程,我们用一个新程序调用 exec on,这恰好导致子进程等待一些 I/O 输入。现在父 init 进程可以等待子进程,但如果它这样做了,那么就没有其他进程 运行。相反,如果 init 进程不等待而是陷入等待循环或其他情况,那么当子进程恢复时,父进程现在占用处理器时间什么都不做。
解决此问题的最佳方法是什么? init 进程是否应该总是 运行 一个无限循环并且我们不担心浪费资源?或者有什么更好的方法吗
如有任何帮助,我们将不胜感激,
本
我不会担心 init 启动期间的资源问题。您的服务器正在启动但未用于其预期目的,因此在此期间对它没有性能要求。
我从未见过在启动过程中写入标准输入的进程,尽管如果您想编写一个,这是可能的。我知道可以使用依赖项编写 init 脚本,具体取决于您使用的发行版以及启动过程的确切内容(upstart、system V init 等)。但默认情况下,它们 运行 以同步方式按照 init 使用的顺序进行。我不确定如何阻止同步过程......等待输入会影响系统。最有可能的是,它会这样做......在继续之前停止并等待输入。
init 进程确实 运行 一个无限循环,但它不使用任何重要资源,因为它是中断驱动的。它只是等待进程死亡或其他信号发送给它。在等待间隔期间,init 使用零 CPU 个周期。
有一个解决方案:SIGCHLD
。当 child 改变其状态(停止或退出)时,它是一个可以传递给 parent 的信号。因此 parent 可以进入休眠状态(例如 sigpause
、sigsuspend
)并且会在 child 终止时被中断,然后 parent 运行适当的信号处理程序调用 wait
系列函数之一。
进程 1 绝不能退出;许多(所有?)Unix 的实现如果确实会导致系统崩溃。
但是,进程 1 不需要做任何事情(我假设内核在转移控制之前在控制台上打开 fds 0、1 和 2给用户 space - 检查你的内核文档以获得 bootstrap 环境的其他细节,如果你真的要自己写 init
:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
pid_t child = fork();
if (child == -1) {
perror("init: fork");
return 1;
}
if (child == 0) {
execl("/etc/rc", "/etc/rc", (char*)0);
perror("/etc/rc");
return 1;
}
for (;;)
wait(0);
}
启动 /etc/rc
后,它 确实 进入无限循环,一遍又一遍地调用 wait
,并丢弃结果。但是 wait
是一个 阻塞 系统调用。每次它被调用时,内核都会从进程 1 中取出 CPU 并将其交给一个有有用工作要做的进程; wait
仅当有已退出的 child 报告时才会 return。 (如果有 no 进程有有用的工作要做,CPU 将进入 low-power "sleep" 状态,直到某些外部事件,例如一个人在键盘上打字或一个网络数据包到达,给 运行 进程一些工作要做。)
有了这个最小的 init
,根据需要保持 运行 完全是 /etc/rc
's responsibility to start up all of the programs needed to make the computer do something useful, and those programs' 的责任;如果它应该通过除此进程之外的每个进程都退出,它将永远睡在 wait
中。更复杂的实现会做更多的事情,例如如果网络服务器崩溃,则重新启动网络服务器。
我对 UNIX 中的 init 进程如何工作有疑问。据我了解,init 进程是第一个启动的,然后其他进程将其分叉。
假设我们启动 init 进程,然后派生一个子进程,我们用一个新程序调用 exec on,这恰好导致子进程等待一些 I/O 输入。现在父 init 进程可以等待子进程,但如果它这样做了,那么就没有其他进程 运行。相反,如果 init 进程不等待而是陷入等待循环或其他情况,那么当子进程恢复时,父进程现在占用处理器时间什么都不做。
解决此问题的最佳方法是什么? init 进程是否应该总是 运行 一个无限循环并且我们不担心浪费资源?或者有什么更好的方法吗
如有任何帮助,我们将不胜感激, 本
我不会担心 init 启动期间的资源问题。您的服务器正在启动但未用于其预期目的,因此在此期间对它没有性能要求。
我从未见过在启动过程中写入标准输入的进程,尽管如果您想编写一个,这是可能的。我知道可以使用依赖项编写 init 脚本,具体取决于您使用的发行版以及启动过程的确切内容(upstart、system V init 等)。但默认情况下,它们 运行 以同步方式按照 init 使用的顺序进行。我不确定如何阻止同步过程......等待输入会影响系统。最有可能的是,它会这样做......在继续之前停止并等待输入。
init 进程确实 运行 一个无限循环,但它不使用任何重要资源,因为它是中断驱动的。它只是等待进程死亡或其他信号发送给它。在等待间隔期间,init 使用零 CPU 个周期。
有一个解决方案:SIGCHLD
。当 child 改变其状态(停止或退出)时,它是一个可以传递给 parent 的信号。因此 parent 可以进入休眠状态(例如 sigpause
、sigsuspend
)并且会在 child 终止时被中断,然后 parent 运行适当的信号处理程序调用 wait
系列函数之一。
进程 1 绝不能退出;许多(所有?)Unix 的实现如果确实会导致系统崩溃。
但是,进程 1 不需要做任何事情(我假设内核在转移控制之前在控制台上打开 fds 0、1 和 2给用户 space - 检查你的内核文档以获得 bootstrap 环境的其他细节,如果你真的要自己写 init
:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
pid_t child = fork();
if (child == -1) {
perror("init: fork");
return 1;
}
if (child == 0) {
execl("/etc/rc", "/etc/rc", (char*)0);
perror("/etc/rc");
return 1;
}
for (;;)
wait(0);
}
启动 /etc/rc
后,它 确实 进入无限循环,一遍又一遍地调用 wait
,并丢弃结果。但是 wait
是一个 阻塞 系统调用。每次它被调用时,内核都会从进程 1 中取出 CPU 并将其交给一个有有用工作要做的进程; wait
仅当有已退出的 child 报告时才会 return。 (如果有 no 进程有有用的工作要做,CPU 将进入 low-power "sleep" 状态,直到某些外部事件,例如一个人在键盘上打字或一个网络数据包到达,给 运行 进程一些工作要做。)
有了这个最小的 init
,根据需要保持 运行 完全是 /etc/rc
's responsibility to start up all of the programs needed to make the computer do something useful, and those programs' 的责任;如果它应该通过除此进程之外的每个进程都退出,它将永远睡在 wait
中。更复杂的实现会做更多的事情,例如如果网络服务器崩溃,则重新启动网络服务器。