wait命令不会等待子进程完成c cpp c ++ [英] wait command wont wait for child process to finish 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屋!