簡體   English   中英

如何將信號從父進程轉發到子進程

[英]how to forward a signal to child process from parent process

我正在實現我自己的 shell,它要求按 CTRL-Z 暫停前台進程。 為了不暫停我的主進程而只暫停子進程,我必須通過主進程中的處理程序捕獲 SIGTSTP 並將其重定向到我的子進程(需要停止)。 但是殺死 function 永遠不會回來。

#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
#include <sys/mman.h>



void handler(){
  pid_t pid;
  int status;
  while((pid = waitpid(-1, &status, 0))>0){
    printf("pid: %d has been reaped\n", pid);
  }
}
  void send_signal(int signum){
     kill(pid, signum);
  }

  void init_signals(){
   //signal(SIGINT, send_signal);
    signal(SIGCHLD, handler);
    signal(SIGTSTP, send_signal);
  }


  void start_foreground_job(char** argv)
  {   
    if( (fork()) ==0)
    {   
        signal(SIGTSTP, SIG_DFL);

        if((execve(argv[0], argv, NULL))<0)//envp
        {
            fprintf(stderr, "%s: Command not found.\n", argv[0]);
            exit(0);
         }
     }

     pause();

     return;
 }

  int main(){
    init_signals();
    char* argv[] ={"/bin/sleep", "10", NULL};

    start_foreground_job(argv);

     printf("This line is what I expected after pressing CTRL-Z\n");

    return 0;
  }

當我在我的環境中嘗試您的代碼時,結果與您相同。 Ctrl+Z后查看子進程的state,

在 Ctrl + Z 之前

ps -aux | grep sleep
16586  0.0  0.0   2016   412 pts/1    S+   10:42   0:00 /bin/sleep 10

Ctrl + Z 之后

ps -aux | grep sleep
16586  0.0  0.0   2016   412 pts/1    T+   10:42   0:00 /bin/sleep 10

子進程的 state 由 S -> T 變化,表示父進程已成功向子進程發送信號。

但是子進程沒有退出,所以你的 waitpid(-1, &status, 0) 不能返回。

選項1:給子進程發送kill信號,waitpid會得到一個返回。

void send_signal(int signum)
{
    if (pid)
    {
        printf("kill %d, signum %d\n", pid, signum);
        //kill(pid, signum);
        kill(pid, SIGKILL );
    }
}

選項2:waitpid api 有一個選項可以等待停止 state:

void handler()
{
    pid_t pid;
    int status;
    while ((pid = waitpid(-1, &status, WSTOPPED)) > 0) {
        printf("pid: %d has been reaped\n", pid);
        break;
    }
}

請檢查以下 sw 版本,它適用於我的工作站。

int pid = 0;
void handler()
{
    pid_t pid;
    int status;
    while ((pid = waitpid(-1, &status, WSTOPPED)) > 0) {
        printf("pid: %d has been reaped\n", pid);
        break;
    }
}
void send_signal(int signum)
{
    if (pid)
    {
        printf("kill %d, signum %d\n", pid, signum);
        kill(pid, signum);
        //kill(pid, SIGKILL );
    }
}

void init_signals()
{
    signal(SIGCHLD, handler);
    signal(SIGTSTP, send_signal);
}


void start_foreground_job(char** argv)
{
    pid = fork();
    if (pid == 0) {
        signal(SIGTSTP, SIG_DFL);

        if ((execve(argv[0], argv, NULL)) < 0) { //envp
            fprintf(stderr, "%s: Command not found.\n", argv[0]);
            exit(0);
        }
    }
    printf("son process pid is %d\n", pid);
    pause();

    return;
}

int main()
{
    init_signals();
    char* argv[] = {"/bin/sleep", "10", NULL};

    start_foreground_job(argv);

    printf("This line is what I expected after pressing CTRL-Z\n");

    return 0;
}

下面是我的測試結果:

./temp
son process pid is 29249
^Zkill 29249, signum 20
pid: 29249 has been reaped
This line is what I expected after pressing CTRL-Z

暫無
暫無

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

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