#c #process
#c #процесс
Вопрос:
Я написал этот код для того, чтобы вычислить факториал числа, используя процессы и pipe()
. Я хотел передать результат от дочернего процесса дочернему процессу. Например, для создания calculate 5! основной, который является отцом, отправляет число 1 в канал. Затем создается первый дочерний процесс, который выполняет 1 * 2, затем он помещает в канал число 2, второй дочерний процесс выполняет 2 * 3, помещает результат в канал и т.д… Кроме того, я использую argv[1][0], думая, что мы запускаем программу следующим образом (./ex3 5), где 5 — это число, из которого мы хотели бы найти факториал. Однако после запуска программы я заметил, что было создано много дочерних процессов (я хотел только 4). Почему это?
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int fd[2];
int w,count=2;
void child_creator(){
pid_t child;
child=fork();
if (child==0) {
close(fd[1]);
read(fd[0],amp;w,sizeof(w));
close(fd[0]);
w=w*count;
count ;
printf("I am child %d , my father is %d , the prod is %dn",getpid(),getppid(),w);
sleep(1);
close(fd[0]);
write(fd[1],amp;w,sizeof(w));
close(fd[1]);
}
}
int main(int argc , char **argv){
int fact=argv[1][0]-'0';
pipe(fd);
w=1;
for (int i=0; i<fact-1; i ){
printf("this is i %dn", i);
child_creator();
}
return 0;
}
После предложенного ответа я попробовал этот код:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int fd[1000][2];
int w,count=1,j=0;
void child_creator(){
pid_t child;
j ;
pipe(fd[j]);
child=fork();
if (child==0) {
close(fd[j-1][1]);
read(fd[j-1][0],amp;w,sizeof(w));
close(fd[j-1][0]);
w=w*count;
printf("I am child %d , my father is %d , the prod is %dn",getpid(),getppid(),w);
sleep(1);
close(fd[j-1][0]);
write(fd[j][1],amp;w,sizeof(w));
close(fd[j][1]);
exit(0);
}
}
int main(int argc , char **argv){
int fact=argv[1][0]-'0';
w=1;
for (int i=0; i<fact-1; i ){
count ;
child_creator();
sleep(2);
}
return 0;
}
Комментарии:
1. Потому что ваши дочерние процессы тоже создают своих дочерних.
2. И родительский, и дочерний продолжают выполнение
for
цикла.3. @EugeneSh. Как мне это исправить и получить тот же результат?
4. @maverick98 Подумайте, вернул ли ‘child_creator(..)’ дочерний pid, поэтому во внешнем цикле:
if (child_creator() == 0) { break /* child doesn't get to loop again! */; }
. Это лучше показывает поток и почему дочерний элемент также выполняет цикл «родители»? Множество вариантов для фактического решения таких..5. Дочерний процесс может завершиться вместо возврата.
Ответ №1:
И родительский, и дочерний процесс возвращаются к for
циклу в main()
. Поскольку дочернему процессу не нужно ничего делать после записи результата, он должен просто завершить работу, а не возвращаться.
У вас также есть проблемы с обработкой дескрипторов файлов канала. Вы делаете это close(fd[1])
в начале дочернего процесса, но позже пытаетесь write(fd[1],amp;w,sizeof(w))
. Вы не можете выполнять запись в закрытый FD. Вам не нужно ничего закрывать, пока дочерний процесс не завершится, а выход из процесса автоматически закрывает все его файлы.
void child_creator(){
pid_t child;
child=fork();
if (child==0) {
read(fd[0],amp;w,sizeof(w));
w=w*count;
count ;
printf("I am child %d , my father is %d , the prod is %dn",getpid(),getppid(),w);
sleep(1);
write(fd[1],amp;w,sizeof(w));
exit(0);
}
}
Комментарии:
1. Я также не уверен в использовании одного и того же канала для каждого дочернего процесса. Вы не можете быть уверены, что они будут записывать и считывать данные в нужном порядке.
2. @maverick98 после вашей правки ваш код все еще закрывается
fd[1]
перед попыткой записи в него…3. @MichaelBeer Как я могу это исправить? Я удалил close(fd[1]); но когда я запускаю программу, она вообще ничего не печатает
4. Объявляйте массив каналов, создавайте новый канал перед каждой развилкой, и каждый дочерний канал использует соответствующий канал для связи со следующим в серии.
5. @Barmar Я пробовал то, что вы сказали, но, по-моему, я делаю что-то не так, я отредактировал сообщение с помощью нового кода