簡體   English   中英

使用信號處理程序暫停/恢復子進程

[英]Using Signal Handlers to Pause/Resume a Child Process

我目前正在嘗試通過使用C中的信號來控制用fork()方法創建的子進程來對C中的信號進行實驗。 本質上,我有一個子進程從linux終端運行“ yes”命令(此命令僅顯示“ y”和換行符,直到終止)。 我希望能夠使用CTRL-Z暫停/恢復此過程。 這就是我現在得到的:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
pid_t CHILD_PROCESS;
pid_t PARENT_PROCESS;
int isPaused;
void pause_handler(int signo){
  if(!isPaused){  
    printf("Ctrl-Z pressed. Pausing child.\n");
    isPaused = 1;
    kill(CHILD_PROCESS,SIGSTOP);
  }
  else if(isPaused){
   printf("\nCtrl-Z pressed. Resuming child.\n");
   kill(CHILD_PROCESS,SIGCONT);
   isPaused = 0;
  }
}

int main(int argc, char** argv){
  pid_t pid;
  PARENT_PROCESS = getpid();
  pid = fork();
  if(pid == 0){
    system("yes");
  }
  isPaused = 0;
  if(pid > 0){
    signal(SIGTSTP, SIG_IGN);
    signal(SIGSTOP, SIG_IGN);
    CHILD_PROCESS = pid;
    while(1){
      if(signal(SIGTSTP,pause_handler) == SIG_ERR){
        printf("Signal Failure");
      }
    }
  }
}

運行此命令時,我可以得到“按下Ctrl-Z。暫停子項”。 通過按CTRL-Z打印到控制台,我可以得到“按Ctrl-Z。恢復子級”。 再次按CTRL-Z打印到控制台。 但是,它實際上並不會一遍又一遍地恢復打印“ y”。 關於子進程為何不恢復的任何想法?

事實證明, system有一個隱式fork調用,因此存儲在CHILD_PROCESS的PID最終實際上不是子進程,而是中間進程。

man 3 system

   The  system()  library  function uses fork(2) to create a child process
   that executes the shell command specified in command using execl(3)  as
   follows:

       execl("/bin/sh", "sh", "-c", command, (char *) 0);

   system() returns after the command has been completed.

因此,如果我們用execl("/bin/sh", "sh", "-c", "yes", NULL)替換system("yes")調用,則可以避免這種額外的派生,並且程序功能為期望。


唯一的其他問題是,根據我在這篇文章中發現的評論,在信號處理程序中使用printf是未定義的行為。 這里不是要擔心的問題,但是將來的代碼要牢記!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM