代码之家  ›  专栏  ›  技术社区  ›  Giorgi Cercvadze

如何将暂停的进程设置为后台?

  •  1
  • Giorgi Cercvadze  · 技术社区  · 6 年前

    我是C语言的新手。我正在尝试制作一个类似shell的程序。我目前正在制作一个信号处理器,这意味着,当进程运行时,有人按下 ctrl键 + Z 该过程应暂停并转到后台,而shell必须继续。这里的问题是:父进程正在 wait(NULL) ,但子级未结束程序,因此基本上父级等待尚未结束程序的子级。如何使父级继续在前台工作。(您可以查看我的代码 How to redirect signal to child process from parent process? 此处)

    1 回复  |  直到 6 年前
        1
  •  2
  •   Monk    6 年前
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    pid_t pid;
    
    void send_signal(int signum){
            kill(pid, signum);
    }
    
    void init_signals(){
            signal(SIGINT, send_signal);
            signal(SIGTSTP, send_signal);
    }
    
    int main(){
            init_signals();
            pid = fork();
            if(pid > 0){
                    //Parent Process
                    printf("PARENT: %d\n", getpid());
                    waitpid(pid, NULL, WUNTRACED);
                    printf("Parent out of wait, i think this is what you are expecting\n");
            } else {
                    struct sigaction act = {{0}};
                    act.sa_handler = send_signal;
                    act.sa_flags = SA_RESETHAND;
                    sigaction(SIGTSTP, &act, NULL);
                    sigaction(SIGINT, &act, NULL);
                    perror("sigaction ");
                    printf("CHILD: %d\n", getpid());
                    // Child Process
                    while(1){
                            usleep(300000);
                    }
            }
            return 0;
    }
    

    我认为以上代码可以满足您的需要。让我解释一下。

    在您的代码中[ How to redirect signal to child process from parent process? 您已经处理了信号,并且从hander上下文发送了相同的信号。当您按下时 Ctrl + c Ctrl + z 父级和子级都接收信号。现在根据处理程序代码

    void send_signal(int signum) {
         kill(pid, signum);
    }
    

    处理程序将在父上下文中执行的时间 pid 将等于 child's pid 所以当处理程序在子上下文中运行时,它将向子上下文发送信号 pid 值将为 0 ,所以它将信号发送给整个过程组,即父进程组和子进程组。这使您可以编写无限次递归运行处理程序的代码。因此,您没有得到期望的结果。

    为了得到理想的结果,我修改了两件事。

    子上下文

    在子上下文中,在进入信号处理程序时将信号操作恢复为默认值,以便在子上下文第二次收到信号时可以执行信号默认操作。

    父上下文

    使用waitpid()而不是wait()。

    pid_t waitpid(pid_t pid, int *status, int options);
    
    The waitpid() system call suspends execution of the calling process until a child specified by pid argument has changed state.  By  default, waitpid() waits only for terminated children, but this behavior is modifiable via the options argument.
    
    `WUNTRACED`   also  return  if  a child has stopped
    

    由于 WUNTRACED 当子进程停止或终止时,父进程将返回。

    我希望这对你有用,如果不行,请问我。