Я вижу четыре проблемы:
1) execlp()
не удается: execlp()
(или любое из семейства функций exec
) полностью заменяет текущий запущенный образ процесса в случае успеха - это не такожидается возвращение, если что-то пойдет не так.Но вы видите сообщение «Ребенок: Закончено спать, возвращаются», поэтому оно не может быть успешно выполнено.(В вашем примере, я бы предположил, что это, вероятно, потому что dmegs
должен был быть dmesg
.)
2) printf()
и cout
буферизация вывода означает, что нет никакой гарантии, что выполучают вывод в том порядке, в котором это происходит.Если вы хотите отладить это путем вывода на печать, вам лучше будет печатать на stderr
(например, с fprintf(stderr, ...)
), который (по умолчанию) не буферизован.
3) Как отмечали другие, wait((void *)pid)
неправильно.wait(NULL)
или waitpid(pid, NULL, 0)
.
4) Является ли эта проблема проблемой или нет, зависит от платформы, но ... аргумент завершающего нулевого указателя на execlp()
должен быть явно записан как (char *)0
а не просто 0
, чтобы гарантировать, что он передается как указатель, а не как целое число.Как правило, в C * 0
в контексте указателя является по определению нулевым указателем, но при передаче параметров в функции с переменным числом аргументов компилятору не хватает информации, чтобы знать, что вы пытаетесь использовать его в указателеконтекст, и поэтому передаст его как целое число, если вы явно не приведете его.Это может привести к неприятностям на платформах, где указатели и целые числа не имеют одинаковый размер.
Поэтому я считаю, что wait()
работает, ребенок на самом деле не выполняет нужную вам команду, ивывод из parent и child запутывается из-за буферизации.
Вот немного измененная версия вашего кода, которая не использует C ++, исключает обработку команд и просто каналывывод от sleep 5
до cat
(что довольно бессмысленно, поскольку sleep
не генерирует никакого вывода в любом случае, но задержка полезна, чтобы увидеть, что происходит):
#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
$