Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ fork()未按预期工作_C++_Linux_Process_Fork - Fatal编程技术网

C++ fork()未按预期工作

C++ fork()未按预期工作,c++,linux,process,fork,C++,Linux,Process,Fork,我正在尝试创建一个程序,它产生两个进程——第一个进程监视第二个进程,如果它被杀死,则重新启动它。(想法是杀死第二个进程的唯一方法是先杀死第一个进程。)下面我有一些代码无法实现我的目标 #include <cstdio> #include <unistd.h> #include <thread> #include <chrono> #include <signal.h> #include <cerrno> void make

我正在尝试创建一个程序,它产生两个进程——第一个进程监视第二个进程,如果它被杀死,则重新启动它。(想法是杀死第二个进程的唯一方法是先杀死第一个进程。)下面我有一些代码无法实现我的目标

#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();
}
#包括
#包括
#包括
#包括
#包括
#包括
void makesides();
作废run_ping(){
while(true){
std::this_thread::sleep_for(std::chrono::seconds(2));
放(Ping);;
}
}
无效运行监视器(pid同级){
while(kill(兄弟,0)!=1,errno!=ESRCH){
printf(“%d仍然存在。\n”,同级);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
使兄弟姐妹();
}
void makesides(){
pid_t pid1,pid2;
if((pid1=fork())=-1){
佩罗尔(“福克”);
退出(退出失败);
}
如果(pid1==0){
setsid();
run_ping();
}
if((pid2=fork())=-1){
佩罗尔(“福克”);
退出(退出失败);
}
如果(pid2==0){
setsid();
运行监视程序(pid1);
}
}
int main(){
使兄弟姐妹();
}
当运行此代码时,它会输出
Ping.
,例如,
7812仍然存在。
每两秒和一秒分别输出一次,如预期的那样。然而,当我从另一个终端
杀死7812
时,“Ping”过程扩散到了一个荒谬的程度——我似乎是在用叉子轰炸自己,只有通过垃圾邮件
killall
我才能恢复


我似乎没有理解关于
fork()
,或者关于
setsid()
的一些微妙之处。请给我一两个指针。

是的,你是。。。您的函数调用
fork()
两次,然后两个子函数最终将递归调用
makesiblines()

当调用
run\u ping()
的第一个子项完成时,它实际上并没有完成,但它将调用
run\u monitor()
。然后它将调用
makesibbins()
并重复,直到它爆炸

解决方案是在运行ping()之后添加一个
exit()
调用:


但是现在,您可以使用
wait()
而不是
kill(pid,0)
,因为
ping()
进程应该是监视器进程的子进程。

在makeSibling函数中,在第二个if块的末尾,添加一个出口(0);或者别的什么。因为你实际上是在用叉子轰炸。 在使用fork时,大多数时候都必须考虑这个出口

。。。int kill(pid_t pid,int sig)。。。如果sig为0(零信号), 执行了错误检查,但没有实际发送信号。空值 信号可用于检查pid的有效性

资料来源:

一方面,您实际上是在创建过程而没有杀死它们


P>另一方面,如果你从另一个终端发送的信号不是杀死,而是只破坏无限循环,第一个兄弟也会执行第二个叉。

这显然是C++,所以我删除了“C”标签。C++,是的,但是问题是C程序员应该解决的问题——我在C++中写的唯一原因是利用SyePyFoE()函数。尽管如此,我还是推迟了。您应该测试
setsid
的故障。您应该使用调试器。不要忘了在
fork
-ing之前刷新流。尝试
strace
你的程序。监视器应该是被监视程序的父进程。您不能禁止进程被
SIGKILL
杀死,我认为删除C标记是一个错误..很好!另一个解决方案是使用if-then-elseinstead@malarres:是的,但是我假设OP程序可能更复杂,并且在
makesiblines()
之后的
main()
中有更多的代码。在本例中,执行
返回
而不是
退出(0)
可能是等效的,但在更复杂的代码中就不是这样了;我发布了我所有的代码。谢谢你的建议!现在我明白我做错了什么。非常感谢。接受这个答案。@Arandur:YW。一条额外的建议。当从多进程应用程序执行printf调试时,在每一行上预先设置写入进程的pid。这将使事情更容易理解。
if (pid1 == 0) {
    setsid();
    run_ping();
    exit(EXIT_SUCCESS); // <------ here!
}
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);
  }
}