0 linux shell process background-process
我想要与这个问题完全相反的问题。我想知道如何创建一个在被终止后继续重新启动的进程。有人能给我一个实施示例吗?
例如,假设我有一个简单的过程,它将时间戳和递增计数器连续记录到日志文件中,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define FILE_PATH "/home/lincoln/date.log"
int main() {
time_t current_time;
struct tm *time_info;
int counter = 0;
while (1) {
FILE *file = fopen(FILE_PATH, "a");
if (file == NULL){
perror("Failed to open the file");
return 1;
}
// Get the current timestamp
time(¤t_time);
time_info = localtime(¤t_time);
// Format the timestamp
char timestamp[25];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", time_info);
// Write timestamp and counter to the file
fprintf(file, "%s | Counter: %d\n", timestamp, counter++);
fflush(file);
fclose(file);
sleep(5); // Sleep for 5 seconds
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为了生成二进制文件(ELF 文件),我使用了以下命令:
gcc logger_file.c -o date_test
Run Code Online (Sandbox Code Playgroud)
(请注意,这只是一个例子。它可能是一个不断打印的“hello world”程序。我选择日志记录是因为我想观察它连续运行的效果。)
从引用的问题(如果我错了请纠正我)来看,它是通过监视子进程的父进程来实现的。如果子进程被终止,父进程会重新启动它。我理解这个概念,但不知道它在实践中是如何实现的。
有人可以演示如何使用提供的二进制示例来实现它吗?(也欢迎链接参考我的研究更多内容。)
如果需要更多信息,请告诉我。
编辑:在我的实现中,我计划在嵌入式设备上进行。基本上,在我的工作环境中,我将sysVinit作为启动系统,将BusyBox v1.23.2作为在 armv7 处理器上运行的 3.18.44 内核上的工具集(我正在使用gcc-12-arm-linux-gnueabi-base
工具链)。
进程一旦死亡就无法自行复活。它已经死了,它实际上不能再做任何事情了(这就是重点)。
\n您可以让一个主管检查进程的状态,并在旧进程死亡时生成一个新进程。
\n几乎所有(除了一些小众或面向小型容器的)Linux 发行版都使这一点变得微不足道:systemd 可以做到这一点,您所需要做的就是编写一个 systemd 服务单元文件并将属性设置Restart=
为、always
或on-abnormal
、 或on-abort
。就是这样!
然后,systemd 充当主管(无需编写自己的主管来摆弄 procfs 或类似的东西),并且一切开箱即用,并且您仍然可以通过显式停止服务重新启动systemctl
。
现在,您问在实践中如何做到这一点。我提到过procfs
;这是方法之一:您只需查看 /proc/{PID} 目录或例如其中的内存映射。
然而,主管通常是这样做的(systemd 的 service.c 也是这样做的),他们注册一个SIGCHLD
处理程序:当进程的子进程退出时,父进程会收到一个信号。因为主管实际上是通过 启动受监督进程作为子进程fork
,所以这是有效的。
因此,您大致需要以下从古老的 Oracle 指南和 Linux 手册页中摘录的内容man waitpid
:
#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\nvoid proc_exit() {\n int wstat;\n pid_t pid;\n\n while (1) {\n int retval = waitpid(pid, &wstat, WNOHANG);\n if (retval == 0)\n return;\n else if (retval == -1)\n return;\n else\n printf("Return code: %d\\n", WEXITSTATUS(wstat));\n }\n}\nint main() {\n signal(SIGCHLD, proc_exit);\n switch (fork()) {\n case -1:\n perror("main: fork");\n exit(0);\n case 0:\n printf("I\'m alive (temporarily)\\n");\n exit(42);\n default:\n pause();\n }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n子进程看到fork
return 0,所以它是打印 的进程"I\'m alive\xe2\x80\xa6
。在这里,如果您想生成一个不同的可执行文件(即您的受监督进程),请调用execve
.