wait命令不会等待子进程完成c cpp c ++ [英] wait command wont wait for child process to finish c cpp c++

查看:61
本文介绍了wait命令不会等待子进程完成c cpp c ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个c ++程序,该程序创建一个子进程,运行一个命令,并将输出通过管道传递回父级正在运行的命令的输入.

I am trying to write a c++ program that creates a child process, runs a command and pipes the output back to the input of a command the parent is running.

我让父母执行wait(NULL)或wait((void *)pid)命令,但它不等待.

I have the parent execute the wait(NULL) or wait((void*)pid) command but it does not wait.

下面是代码:

#include <string.h>
#include <fstream>
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
using namespace std;

int main(int argc, char * argv[])
{    
        char* commands[strlen(argv[1])];
        char *command = NULL;
        command = strtok(argv[1],"|");
        int i = 0;
        while(command != NULL)
        {
                commands[i] = command;
                i++;
                command = strtok(NULL,"|");
        }

        int numberOfCommands = i;

        pid_t pid;
        int pfd[2];
        char* prgname = NULL;
        if(pipe(pfd) == -1)
        {
                perror("error on pipe call");
                return(1);
        }

        for(int j = 0;j<numberOfCommands;j++)
        {
                cout<<commands[j]<<endl;
        }

        pid = fork();
        if(pid == 0){//child process
                printf("Child: My PID = %d\n", getpid());
                printf("Child: Running...\n");
                close(pfd[0]); //close read end of pipe
                dup2(pfd[1],1);//connect the pipes
                close(pfd[1]);//close extra file descriptors
                prgname = commands[0];//first command
                cout<<"child starting command: "<<prgname<<endl;
                execlp(prgname, prgname, 0);//Load the program
                **printf("Child: Done sleeping, returning.\n");**
        }
        else
        {
                printf("Parent: My PID = %d\n", getpid());
                **wait((void*)pid); //also tried wait(NULL); same effect
                printf("Parent: Running...\n");**
                close(pfd[1]); //close the write end of the pipe
                dup2(pfd[0],0);//connect the pipes
                close(pfd[0]); //close extra file descriptor
                prgname = commands[1];//now run the second command
                cout<<"parent starting command: "<<prgname<<endl;
                execlp(prgname, prgname, 0);//Load the programm
        }
        cout<<"all done"<<endl;
        return 0;
}

不要使用粗体字.我希望父进程等待wait()命令,然后子进程将打印出子进程正在休眠...",然后完成操作,然后父进程将打印出父进程:正在运行..."

Take not of the bolded lines. I would expect the parent process to wait at the wait() command and the child would print out "Child done sleeping..." and then finish and then the parent would print out "Parent: running..."

我在做什么错了!

谢谢!

更新:程序的完整输出为:

Update: full output to program is:

dmegs
more
Child: My PID = 30070
Child: Running...
Parent: My PID = 30066
Parent: Running...
parent starting command: more
child starting command: dmegs
Child: Done sleeping, returning.
all done

推荐答案

我看到四个问题:

1) execlp()失败: execlp()(或任何 exec 函数家族)完全替换了当前正在运行的过程映像(如果成功)-除非出现问题,否则它不会返回.但是您看到的是孩子:睡着了,回去了"的消息,所以它不可能成功.(在您的示例中,我想这可能是因为 dmegs 应该是 dmesg .)

1) execlp() is failing: execlp() (or any of the exec family of functions) completely replaces the currently running process image if successful - it is not expected to return, unless something goes wrong. But you are seeing the "Child: Done sleeping, returning" message, so it cannot have succeeded. (In your example, I would guess that this is probably because dmegs should have been dmesg.)

2) printf() cout 输出缓冲意味着无法保证您按输出顺序获得输出.如果要通过打印输出进行调试,最好将其打印到 stderr (例如,使用 fprintf(stderr,...))(默认情况下)无缓冲的.

2) printf() and cout output buffering means that there is no guarantee whatsoever that you are getting the output in the order in which it happens. If you want to debug this by printing output, you would be better off printing to stderr (e.g. with fprintf(stderr, ...)) which is (by default) unbuffered.

3)如其他人所述, wait((void *)pid)是错误的. wait(NULL) waitpid(pid,NULL,0).

3) As noted by others, wait((void *)pid) is wrong. wait(NULL) or waitpid(pid, NULL, 0).

4)这个问题是否与平台有关,但是...终止于 execlp()的空指针参数应明确写为(char *)0 ,而不只是 0 ,以确保将其作为指针而不是整数传递.通常,在C语言中,指针上下文中的 0 根据定义是一个空指针,但是当将参数传递给具有可变数量参数的函数时,编译器没有足够的信息来知道您要尝试执行以下操作:在指针上下文中使用它,因此除非您明确地将其强制转换,否则它将作为整数传递.在指针和整数大小不相同的平台上,这可能会给您带来麻烦.

4) Whether this one is a problem or not is platform-dependent, but... the terminating null pointer argument to execlp() should be explicitly written as (char *)0 rather than just 0, to ensure that it is passed as a pointer rather than an integer. In general in C, 0 in a pointer context is by definition a null pointer, but when passing parameters to functions with variable numbers of arguments, the compiler does not have enough information to know that you are trying to use it in a pointer context, and so will pass it as an integer unless you explicitly cast it. This can get you into trouble on platforms where pointers and integers are not the same size.

所以我认为 wait()在工作,子进程实际上没有运行您想要的命令,并且由于缓冲,父子进程的输出变得混乱了.

So I reckon the wait() is working, the child is not actually running the command you want, and the output from parent and child is getting mixed up due to buffering.

这里是您的代码的略微修改版本,它不使用任何C ++,削减了命令处理内容,仅将 sleep 5 的输出传递给 cat (这很没有意义,因为 sleep 仍然不会生成任何输出,但是延迟对于查看发生了什么很有用):

Here is a slightly modified version of your code, which doesn't use any C++, cuts out the command handling stuff, and just pipes the output of sleep 5 to cat (which is rather pointless, as sleep doesn't generate any output anyway, but the delay is useful to see what's going on):

#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void)
{    
        pid_t pid;
        int pfd[2];
        if(pipe(pfd) == -1)
        {
                perror("error on pipe call");
                return(1);
        }

        pid = fork();
        if(pid == 0){//child process
                fprintf(stderr, "Child: My PID = %d\n", getpid());
                fprintf(stderr, "Child: Running...\n");
                close(pfd[0]); //close read end of pipe
                dup2(pfd[1],1);//connect the pipes
                close(pfd[1]);//close extra file descriptors
                fprintf(stderr, "child starting command: sleep 5\n");
                execlp("sleep", "sleep", "5", (char *)0);//Load the program
                fprintf(stderr, "child: execlp failed\n");
        }
        else
        {
                fprintf(stderr,"Parent: My PID = %d\n", getpid());
                wait(NULL);
                fprintf(stderr,"Parent: Running...\n");
                close(pfd[1]); //close the write end of the pipe
                dup2(pfd[0],0);//connect the pipes
                close(pfd[0]); //close extra file descriptor
                fprintf(stderr,"parent starting command: cat\n");
                execlp("cat", "cat", (char *)0);//Load the programm
        }
        fprintf(stderr,"all done\n");
        return 0;
}

输出:

$ gcc -Wall -o wait wait.c
$ ./wait
Child: My PID = 27846
Child: Running...
child starting command: sleep 5
Parent: My PID = 27845

(这里有5秒的延迟)

Parent: Running...
parent starting command: cat
$

这篇关于wait命令不会等待子进程完成c cpp c ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆