停止进程,然后再次使用它而不终止它

时间:2019-03-15 15:28:32

标签: c process

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);
      }

这应该打印两次“ Entered Handler”,但不会打印两次。可能是因为它无法再次呼叫孩子。我能以某种方式纠正吗?

1 个答案:

答案 0 :(得分:1)

  

这应该打印两次“ Entered Handler”,但不会打印两次。   可能是因为它无法再次呼叫孩子。

这里存在多个问题,但是通常无法将SIGINT两次交付给同一进程不是其中之一。问题包括:

  • 信号处理程序将SIGKILL传递给它正在运行的进程,从而使该进程立即终止。一旦终止,该过程将不再响应其他信号,因此没有理由期望孩子会两次打印“输入的处理程序”。
  • 在为SIGINT安装处理程序的孩子与向其发送该信号的父母之间存在竞争状态。如果子级在为其安装处理程序之前接收到该信号,则该子级将终止而不产生 any 输出。
  • 在孩子接受的第一个信号和传递给孩子的第二个信号之间存在竞争状态。正常信号不会排队,因此如果在第一个信号仍未决时传送第二个信号,则第二个信号将丢失。
  • pause()中的子级阻塞与父级信令之间存在竞争状态。如果信号处理程序没有杀死孩子,那么孩子可能会在到达pause()调用之前接收到两个信号,因此根本无法终止。
  • 如果孩子在父母首先发信号通知之前阻止pause()的活动,并且如果它没有通过自己给SIGKILL自杀而自杀,那么该信号应促使它解锁并从pause()返回正常终止的路径。因此,在第二个信号的传递和孩子的正常终止之间也会出现竞争状况。
  • printf()函数不是异步信号安全的。从信号处理程序调用它会产生不确定的行为。
  • 您应始终使用sigaction()来安装信号处理程序,而不要安装signal(),因为signal()的行为未明确说明并且在实践中会有所不同。 signal()的唯一安全用途是将信号处置重置为其默认设置。
  

我可以改正吗   某种方式?

  1. 从信号处理程序中删除kill()调用。
  2. 用相应的printf()调用替换信号处理程序中的write()调用。
  3. 使用sigaction()代替signal()来安装处理程序。默认标志应适合您使用。
  4. 通过以下方式解决各种比赛条件
    1. 在派生之前具有父块SIGINT(通过sigprocmask()),以便最初将其在子对象中阻塞。
    2. 让孩子使用带有适当信号掩码的sigsuspend()代替pause()
    3. 让孩子从sigsuspend()返回后向父母发送某种响应(可能是其自身的信号,或者是父母可以读取的对管道的写操作),并让父母等待该响应在发送第二个信号之前。
    4. 让孩子再次呼叫sigsuspend()来接收第二个信号。