停止进程然后再次使用它而不会杀死它

问题描述 投票:-1回答:1

有没有办法在C编程语言中,停止子进程,然后再次调用它从头开始?我已经意识到如果我使用SIGKILL然后再次调用子进程没有任何反应。

void handler {
       printf(“entered handler”);
       kill(getpid(),SIGKILL);
}

int main () {
      pid_t child;
     child=fork();
      if (child<0) printf(“error”);
      else if (child==0) {
             signal(SIGINT,handler);
              pause();
     }
      else { 
           kill(child,SIGINT);
           kill(child,SIGINT);
      }

这应该打印两次“输入处理程序”,但它不会。可能是因为它无法再次召唤孩子。我可以用某种方式纠正这个问题吗?

c process
1个回答
1
投票

这应该打印两次“输入处理程序”,但它不会。可能是因为它无法再次召唤孩子。

这里有几个问题,但一般无法将SIGINT两次交付给同一个过程并不是其中之一。问题包括:

  • 信号处理程序将SIGKILL传递给它运行的进程,从而影响该进程的立即终止。一旦终止,该过程将不会响应更多信号,因此没有理由期望孩子将两次打印“输入的处理程序”。
  • 安装SIGINT处理程序的孩子和发送该信号的父母之间存在竞争条件。如果孩子在为它安装处理程序之前收到信号,那么孩子将终止而不产生任何输出。
  • 在孩子接受的第一个信号和第二个信号被传递给它之间存在竞争条件。正常信号不会排队,因此如果在第一个信号仍然未决时传送,则第二个信号将丢失。
  • 阻塞pause()的孩子和父母信号之间存在竞争条件。如果信号处理程序没有杀死孩子,那么孩子有可能在到达pause()呼叫之前接收两个信号,因此根本不能终止。
  • 如果孩子在父母第一次发出信号之前让它在pause()中阻塞,并且如果它没有通过传递自己的SIGKILL而自杀,那么该信号应该使其解锁并从pause()返回,在终止的路径上一般。因此,在第二信号的传递和儿童的正常终止之间也存在竞争条件。
  • printf()函数不是异步信号安全的。从信号处理程序调用它会产生未定义的行为。
  • 你应该总是使用sigaction()安装信号处理程序,而不是signal(),因为signal()的行为是不明确的,并且在实践中有所不同。 signal()唯一安全的用途是将信号的处置重置为默认值。

我可以用某种方式纠正这个问题吗?

  1. 从信号处理程序中删除kill()调用。
  2. 用相应的printf()调用替换信号处理程序中的write()调用。
  3. 使用sigaction()而不是signal()来安装处理程序。默认标志应该适合您的使用。
  4. 解决各种竞争条件 在分叉之前让父母阻止SIGINT(通过sigprocmask()),这样它最初将被封锁在孩子身上。 让孩子使用sigsuspend(),使用适当的信号掩码,而不是pause()。 让孩子从sigsuspend()返回之后向父母发送某种响应(可能是他自己的信号,或者是父母可以读取的管道的写入),并且在发送第二个信号之前让父母等待该响应。 让孩子第二次打电话给sigsuspend()接收第二个信号。
© www.soinside.com 2019 - 2024. All rights reserved.