MaheshGupta024 выявили очень важную проблему в вашем коде; Я полагаю, вы это исправите.
Одна из других проблемных областей:
close(1);
if (dup2(pipefd[0], 0)==-1)
perror("Can't redirect stdin");
close(pipefd[1]);
for (i=1; i< argc; i++){
if ((wait(NULL))== -1)
perror("Wait error");
while ((c= read(pipefd[0], readin, SIZE)) > 0){;
//print buf count
total += atoi(readin);
}
}
Первое закрытие закрывает стандартный вывод процесса; это редко хорошая идея. Следующая строка дублирует конец чтения канала для стандартного ввода - это нормально. Как отмечено в комментарии выше, perror()
не завершается. Затем вы закрываете конец записи канала - это правильно; но вы, вероятно, должны также закрыть конец чтения канала, так как вы установили его для выхода из канала.
Ваш цикл начинается нормально; у вас есть лишние скобки в строке wait()
. Вы читаете из pipefd[0]
вместо стандартного ввода - так что, возможно, вы не хотели закрывать pipefd [0], но вам также не нужно было дублировать его на стандартный ввод. Затем у вас есть вложенный цикл, который читает по каналу, в то время как у дочернего элемента есть больше данных для чтения - вам совершенно не нужен код wait()
с его циклом, поскольку внутреннее while не завершится, пока все дочерние элементы не будут мертвы , С другой стороны, в этом нет большого вреда - после того, как умирает первый дочерний элемент, вы читаете данные всех остальных дочерних элементов, затем переходите во внешний цикл и ждете друг друга, причем внутренний цикл немедленно завершается, так как нет данных для чтения.
Итак:
- Не закрывать стандартный вывод.
- Не дублируйте канал, прочитанный на стандартный ввод.
- Решите, хотите ли вы очистить цикл - он будет работать, но может быть чище.
Функция run()
:
void run(char *f){
int fp;
if ((fp= open(f, O_RDONLY)) == -1)
perror("Can't open the file");
close(pipefd[0]);
dup2(pipefd[1], 1);
close(pipefd[1]);
execlp("ls1", f, NULL);
}
Аргумент должен быть const char *f
(или использовать name
или file
вместо f
). Я бы также передал массив pipefd
в функцию вместо использования глобальной переменной
,
Не вызывайте файловый дескриптор fp
; это имя условно обозначает переменную типа FILE *
, а не int
.
Однако вам не нужно открывать файл в первую очередь - если только вы не хотите, чтобы вызывающая программа создавала отчеты об ошибках вместо вызываемой программы. Однако, если вы хотите, чтобы вызывающая программа создавала отчеты об ошибках, вы должны закрыть файловый дескриптор, прежде чем продолжить. (Я уже прокомментировал возвращение perror()
).
Было бы неплохо напечатать сообщение об ошибке после execlp()
; единственный раз, когда функция возвращается, когда она терпит неудачу, поэтому нет необходимости проверять ее возвращаемое значение. Возможно, вы захотите выйти - вместо того, чтобы неисправная функция прошла через остальную часть основной программы после вызова run()
.
Хорошие моменты: вы закрыли оба дескриптора файла канала.
Таким образом:
void run(const char *file, int *pipefd)
{
close(pipefd[0]);
dup2(pipefd[1], 1);
close(pipefd[1]);
execlp("ls1", f, NULL);
perror("Failed to exec ls1");
exit(EXIT_FAILURE);
}