Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在用户输入时终止waitpid?_C_Fork - Fatal编程技术网

C 如何在用户输入时终止waitpid?

C 如何在用户输入时终止waitpid?,c,fork,C,Fork,我正在使用C语言开发一个基于ncurses的文件管理器。问题是,一些子进程可能需要一些时间才能完成,在完成之前,由于waitpid的原因,它一直处于停滞状态 我不能使用WNOHANG标志,因为下一个代码块取决于子进程的输出 void getArchivePreview(char *filepath, int maxy, int maxx) { pid_t pid; int fd; int null_fd; // Reallocate `temp_dir` and

我正在使用C语言开发一个基于ncurses的文件管理器。问题是,一些子进程可能需要一些时间才能完成,在完成之前,由于
waitpid
的原因,它一直处于停滞状态

我不能使用
WNOHANG
标志,因为下一个代码块取决于子进程的输出

void getArchivePreview(char *filepath, int maxy, int maxx)
{
    pid_t pid;
    int fd;
    int null_fd;

    // Reallocate `temp_dir` and store path to preview file
    char *preview_path = NULL;
    allocSize = snprintf(NULL, 0, "%s/preview", cache_path);
    preview_path = malloc(allocSize+1);
    if(preview_path == NULL)
    {
        endwin();
        printf("%s\n", "Couldn't allocate memory!");
        exit(1);
    }
    snprintf(preview_path, allocSize+1, "%s/preview", cache_path);

    // Create a child process to run "atool -lq filepath > ~/.cache/cfiles/preview"
    pid = fork();
    if( pid == 0 )
    {
        remove(preview_path);
        fd = open(preview_path, O_CREAT | O_WRONLY, 0755);
        null_fd = open("/dev/null", O_WRONLY);
        // Redirect stdout
        dup2(fd, 1);
        // Redirect errors to /dev/null
        dup2(null_fd, 2);
        execlp("atool", "atool", "-lq", filepath, (char *)0);
        exit(1);
    }
    else
    {
        int status;
        waitpid(pid, &status, 0);
        getTextPreview(preview_path, maxy, maxx);
        free(preview_path);
    }
}

在这种情况下,如果用户决定转到其他文件,我希望继续执行程序的其余部分。我可以用什么方式更改程序的体系结构?

如果我正确理解了这个问题,那么您希望在完成子项或任何用户输入时取消阻止父项

正如注释中所建议的,您可以处理
SIGCHLD
和另一个信号,比如
SIGUSR1
<当您获得用户输入时,将引发代码>SIGUSR1。下面是处理
SIGCHLD
和'SIGUSR1'的示例。如果使用输入任何数字,则会将
SIGUSR1
提升到父级和父级
kill
子级。否则子项将在退出时发出
SIGCHLD

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

int raised_signal = -1; 

static void cb_sig(int signal)
{
        if (signal == SIGUSR1)
                raised_signal = SIGUSR1;
        else if (signal == SIGCHLD)
                raised_signal = SIGCHLD;
}

int main()
{
        int pid;
        int i, a;
        struct sigaction act;

        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        act.sa_handler = cb_sig;

        if (sigaction(SIGUSR1, &act, NULL) == -1) 
                printf("unable to handle siguser1\n");
        if (sigaction(SIGCHLD, &act, NULL) == -1) 
                printf("unable to handle sigchild\n");

        pid = fork();
        if (pid == 0) {
                /* child */
                for (i = 0; i < 10; i++) {
                        sleep(1);
                        printf("child is working\n");
                }
                exit(1);
        } else {
                /* parent */
                if (-1 ==  scanf("%d", &a)) {
                        if (errno == EINTR)
                                printf("scanf interrupted by signal\n");
                } else {
                        raise(SIGUSR1);
                }

                if (raised_signal == SIGUSR1) {
                        printf("user terminated\n");
                        kill(pid, SIGINT);
                } else if (raised_signal == SIGCHLD) {
                        printf("child done working\n");
                }

                exit(1);
        }

        return 0;
}
#包括
#包括
#包括
#包括
#包括
int raised_信号=-1;
静态无效cb_信号(内部信号)
{
如果(信号==SIGUSR1)
升高的信号=SIGUSR1;
否则如果(信号==SIGCHLD)
升高的信号=SIGCHLD;
}
int main()
{
int-pid;
int i,a;
结构动作法;
sigemptyset(和act.sa_面具);
act.sa_标志=0;
act.sa_handler=cb_sig;
if(sigaction(SIGUSR1,&act,NULL)=-1)
printf(“无法处理siguser1\n”);
if(sigaction(SIGCHLD,&act,NULL)=-1)
printf(“无法处理sigchild\n”);
pid=fork();
如果(pid==0){
/*孩子*/
对于(i=0;i<10;i++){
睡眠(1);
printf(“孩子正在工作”\n);
}
出口(1);
}否则{
/*母公司*/
如果(-1==scanf(“%d”、&a)){
如果(errno==EINTR)
printf(“scanf被信号中断\n”);
}否则{
升高(SIGUSR1);
}
if(上升的信号==SIGUSR1){
printf(“用户终止\n”);
kill(pid,SIGINT);
}else if(升高的信号==SIGCHLD){
printf(“子工作完成”\n);
}
出口(1);
}
返回0;
}

<代码>可以考虑使用<代码> SigActudio<代码>处理程序来代替<代码> SigCHLLD?这样,您可以等待子进程退出(由信号处理程序指示)或输入。它如何同时等待这两个进程?如果我理解正确,它要么等孩子,要么等孩子input@Hasturkun,如果我理解正确,请使用
sigaction
处理
SIGCHLD
并说
SIGUSR1
,使用
raise
在用户输入时发出
SIGUSR1
信号。@JohnLeaf:如果使用
选择
(或
poll
),您可以使用
socketpair
eventfd
signalfd
(前两个由信号处理程序写入)来等待输入和子终止。还存在其他类似选项。(部分取决于您的程序是否为多线程)做两个分叉?嗨,谢谢你的回复。你的代码对我来说很好,但当我尝试在代码中实现时(如图所示),程序只是挂起并退出,在任何输入上都会出现错误
用户定义信号1
。有什么原因会出现错误吗?还有一个问题,我想我要单独评论一下。你能解释一下为什么
if(-1==scanf(“%d”,&a))
不阻塞?不会
scanf
等待输入吗?我看不到
sigaction(SIGCHLD,&act,NULL)
sigaction(SIGUSR1,&act,NULL)
在您的代码中被调用。如果您以后不想使用它,也请注意。您好,我正在阅读有关信号处理的更多信息,我了解到您不能从信号处理程序修改全局变量,除非它们属于
volatile sig_atomic_t
类型,但在我的代码中,我正在从信号处理程序更改
int-rised_signal
。这是为什么?是的,如果您试图从信号和主进程更新全局变量,则有可能出现争用情况。在这种情况下,我们正在从信号处理程序更新
提升的_信号
,主进程只是读取变量。因此,在给定时间,这将不会有两个单独的
提升的_信号
。如就原子变量而言,它保证变量将在一条指令中更新,这样我们就不会有它的多个副本。这只是一个例子,您可以进一步阅读“Robert Love的Linux系统编程”中的“信号”一章