fork()未按预期工作
fork() not working as expected
我正试图创建一个程序,该程序产生两个进程——第一个进程监视第二个进程,如果它被终止,则重新启动它。(这个想法是,杀死第二个进程的唯一方法是先杀死第一个进程。)下面我有一些代码无法实现我的目标。
#include <cstdio>
#include <unistd.h>
#include <thread>
#include <chrono>
#include <signal.h>
#include <cerrno>
void makeSiblings();
void run_ping() {
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(2));
puts("Ping.");
}
}
void run_monitor(pid_t sibling) {
while (kill(sibling, 0) != -1 and errno != ESRCH) {
printf("%d still exists.n", sibling);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
makeSiblings();
}
void makeSiblings() {
pid_t pid1, pid2;
if ((pid1 = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid1 == 0) {
setsid();
run_ping();
}
if ((pid2 = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid2 == 0) {
setsid();
run_monitor(pid1);
}
}
int main() {
makeSiblings();
}
当运行此代码时,它会分别每两秒和一秒输出Ping.
和7812 still exists.
,正如预期的那样。然而,当我来自另一个终端kill 7812
时,"Ping"过程激增到了荒谬的程度——我似乎在轰炸自己,只有通过垃圾邮件killall
,我才能恢复。
我似乎没有理解关于fork()
或setsid()
的一些微妙之处。我希望能给你一两个指针。
是的,你是fork炸弹。。。您的函数调用fork()
两次,然后两个子函数最终都将递归地调用makeSiblings()
。
当第一个孩子,即调用run_ping()
的孩子完成时,它实际上并没有完成,但它将调用run_monitor()
。然后它会调用makeSiblings()
并重复,直到它爆炸!
解决方案是在run_ping()
:之后添加一个exit()
调用
if (pid1 == 0) {
setsid();
run_ping();
exit(EXIT_SUCCESS); // <------ here!
}
还要注意,您正在makeSiblings()
和run_monitor()
之间执行尾部递归,这可能不是一个好主意,因为您的堆栈可能会溢出。
我会写这样的东西:
void run_monitor(pid_t sibling) {
while (kill(sibling, 0) != -1 and errno != ESRCH) {
//...
}
}
void makeSiblings() {
pid_t pid2 = fork(); //error code ommited
setsid();
if (pid2 != 0)
return;
//this is now the monitor process
while (true) {
pid_t pid1 = fork(); //error code ommited
if (pid1 == 0) {
setsid();
run_ping();
exit(EXIT_SUCCESS);
}
run_monitor(pid1);
}
}
但是现在,您只需要使用wait()
而不是kill(pid, 0)
,因为ping()
进程是监视器进程的子进程,这是应该的。
在makeSibling函数中,在第二个if块的末尾添加一个exit(0);或者什么的。因为你实际上是在轰炸。在使用fork时,您必须在大多数时候考虑该出口。
int kill(pid_t pid,int sig)。。。如果sig是0(零信号),执行错误检查,但实际上没有发送信号。null信号可以用来检查pid的有效性。。。
来源:http://linux.die.net/man/3/kill
一方面,你们实际上是在创造过程而不杀死他们。
另一方面,如果你从另一个终端发送的信号不是杀死,而是破坏了无限循环,那么第一个同级也会执行第二个fork。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- execlp() 在 fork() 之后无法正常工作
- 我试图了解 fork() 函数序列是如何工作的?
- fork()未按预期工作
- fork() 在 C++ 中的工作