【问题标题】:How to set the paused process to background?如何将暂停的进程设置为后台?
【发布时间】:2018-08-26 02:31:32
【问题描述】:

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

【问题讨论】:

  • 不是等待所有的孩子,主程序应该对信号说 SIGCHLD 孩子已经终止,然后通过适当的“等待”调用来接收它。

标签: c shell process signals fork


【解决方案1】:
#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? 中,您已经处理了信号,并且从处理程序上下文发送了相同的信号。当您按下 Ctrl + cCtrl + 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父进程将在子进程停止或终止时返回。

我希望它对你有用,请问我是否没有。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    • 2023-03-29
    • 1970-01-01
    相关资源
    最近更新 更多