2016-12-10 3 views
1

Мне нужно создать программу, которая создает 4 детей. первый ребенок должен передать только массив ints (массив передается из аргументов) в следующий, второй должен увеличить все значения на 20% и передать их, третий должен увеличить их на 30%, а четвертый должен распечатать их все , До сих пор мне удалось это сделать, но я еще не совсем понял трубы, или, скорее, как передать массив через них.Передача массива int с неназванными трубами

РЕДАКТИРОВАТЬ: многое из этого вышло, хотя теперь моя программа иногда зависает и не обрабатывает входы.

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 

int main(int argc, char* argv[]) 
{ 
int kom_pipe[2]; 
int kom_pipe2[2]; 
int n,i; 
double prices[argc-1]; 

pipe(kom_pipe); 
pipe(kom_pipe2); 

for(n = 1; n<argc; n++){//fill array 
    prices[n-1] = strtol(argv[n],NULL, 10); 
} 

//write(kom_pipe[1],&prices,sizeof(int)*(argc-1)); 

for(n = 0; n<4; n++){ 
    switch(fork()){ 
     case -1: 
      perror("error with fork"); 
     return -1; 
     case 0:; 
      double prices2[argc-1];   
      if(n==0){ 
       close(kom_pipe[1]); 
       close(kom_pipe2[0]); 
       //read(kom_pipe[0],&prices2,sizeof(int)*(argc-1));  
       write(kom_pipe2[1],&prices,sizeof(double)*(argc-1)); 
       /*for(i = 0; i<argc-1; i++){ 
        printf("%.5f ",prices[i]); 
       } 
      printf("\n");*/ 


      }else if(n==1){ 
       close(kom_pipe[0]); 
       close(kom_pipe2[1]); 
       read(kom_pipe2[0],&prices2,sizeof(double)*(argc-1));   


       for(i = 0; i<argc-1; i++){ 
        prices2[i]*=1.2; 
       } 
       write(kom_pipe[1],&prices2,sizeof(double)*(argc-1)); 


      }else if(n==2){ 

       close(kom_pipe2[0]); 
       close(kom_pipe[1]); 
       read(kom_pipe[0],&prices2,sizeof(double)*(argc-1)); 
       for(i = 0; i<argc-1; i++){ 
        prices2[i]*=1.3; 
       } 
       write(kom_pipe2[1],&prices2,sizeof(double)*(argc-1)); 


      }else if(n==3){ 
       close(kom_pipe[0]); 
       close(kom_pipe2[1]); 
       read(kom_pipe2[0],&prices2,sizeof(double)*(argc-1)); 
       for(i = 0; i<argc-1; i++){ 
        printf("%.5f ",prices2[i]); 
       } 
      printf("\n"); 
     } 
    close(kom_pipe[0]); 
    close(kom_pipe2[0]); 
    close(kom_pipe[1]); 
    close(kom_pipe2[1]); 
    _exit(0); 
    } 
} 

close(kom_pipe[0]); 
close(kom_pipe2[0]); 
sleep(1); 
close(kom_pipe[1]); 
close(kom_pipe2[1]); 
for(n = 0; n<4; n++){ 
    wait(); 
} 
return 0; 
} 
+0

спасибо, что напомнилось мне, было быстро редактировать –

ответ

1

Ваша программа подлежит определению race conditions. Дети, которые вы создаете, могут выполняться в любом порядке и даже параллельно. Так, если сначала происходит n == 0, а затем n == 3, вход записывается в kom_pipe2 по первому, начиная с kom_pipe2, причем последний печатается без изменений, а остальные два подпроцесса будут висеть, потому что n == 1 ждет вход, который уже был заявлен кто-то еще и n == 2 зависит от n == 1. Ваше письмо и чтение массива в основном прекрасны, просто не используйте один и тот же канал для двух разных целей.

Это может по-прежнему ломаться в редком случае, когда один из write s будет прерван посередине, а read не найдет все данные. Вот для чего возвращается значение read. В идеале вы должны написать цикл, который пытается заполнить буфер постепенно и только после того, как данные будут получены полностью. В трубах с несколькими байтами полезной нагрузки это не будет проблемой, но это ежедневный хлеб с IP-сокетами.

Обратите внимание, что ваш код не дает никаких преимуществ перед выполнением всех операций в последовательности. Даже если вы передадите исходный массив в целом, фильтры по пути могут быть распараллелены лучше, если они читают double s один за другим. Если это было задание, которое могло бы быть тем, что ожидалось.

В стороне замечания,

  • Если заменить _exit() на exit() вам не нужно, чтобы закрыть все трубы, это сделано для вас. И в любом случае вам не нужно закрывать их в родительском процессе. Есть ли конкретная причина не использовать exit()?

  • sleep() в конце совершенно бесполезен, а произвольная 1 секунда не является признаком хорошего кода. wait() позаботится о ожидании подпроцессов. (Также проверьте его возвращаемое значение, чтобы наблюдать за прерываниями другими сигналами, чем SIGCHLD.)

 Смежные вопросы

  • Нет связанных вопросов^_^