Обратите внимание, что 'dup(p[1])
' означает, что у вас есть два файловых дескриптора, указывающих на один и тот же файл. Не закрывается p[1]
; Вы должны сделать это явно. Аналогично с 'dup(p[0])
'. Обратите внимание, что файловый дескриптор, читающий из канала, возвращает нулевые байты (EOF) только тогда, когда для канала нет открытых дескрипторов файла записи; пока последний дескриптор записи не будет закрыт, процесс чтения будет зависать бесконечно. Если вы dup()
завершили запись, есть два открытых файловых дескриптора до конца записи, и оба должны быть закрыты до того, как процесс чтения получит EOF.
Вам также не нужен или не требуется вызов wait()
в вашем коде. Если список ls
больше, чем может содержать канал, ваши процессы будут заблокированы, когда ребенок ожидает завершения ls
и ls
, ожидая, пока ребенок продолжит чтение записанных данных. *
Когда лишний материал удаляется, рабочий код становится:
#include <unistd.h>
int main(void)
{
int p[2];
pid_t ret;
pipe(p);
ret = fork();
if (ret == 0)
{
close(1);
dup(p[1]);
close(p[0]);
close(p[1]);
execlp("ls", "ls", "-l", (char *) 0);
}
else if (ret > 0)
{
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
execlp("wc", "wc", "-l", (char *) 0);
}
return(-1);
}
В Solaris 10 он компилируется без предупреждения с помощью:
Black JL: gcc -Wall -Werror -Wmissing-prototypes -Wstrict-prototypes -o x x.c
Black JL: ./x
77
Black JL: