2017-01-30 12 views
0

У меня проблема с этой знаменитой проблемой. Я должен раскошелиться на двух детей (производителя и потребителя), которые общаются благодаря трубе. Первый ребенок (продюсер) должен прочитать строки из stdin, отправить их второму ребенку (потребителю), который должен преобразовать их в верхний регистр и распечатать на стандартный вывод.производитель-потребитель между двумя детьми раздвоенный [C]

Я написал код, но он не работает.

  • Потребитель читает строку из stdin и записывает ее в трубку рядом с ней (включая '\ 0').
  • Производитель считывает MAXC из трубы и разбивается на две длины и строку var. Когда я печатаю длину, устанавливается большое число. Поэтому даже строка, которая должна быть преобразована, неверна. Кроме того, вся программа зависает.

(я пытался писать здесь код, но может быть, я не понимаю, как сделать это правильно объяснить мне спасибо.!)

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <fcntl.h> 
#include <ctype.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/wait.h> 
#define MAXC 30 
static void signalHandler(int signo) 
{ 
    return; 
} 
pid_t pids[2]; 
int main() 
{ 
    int fd[2], i, nW; 
    size_t l; 
    char string[MAXC+1], stringtoup[MAXC+1], tmp[MAXC+1]; 

    signal(SIGUSR1, signalHandler); 
    if(pipe(fd)==0) 
    {  
     pids[0]=fork(); 
     if(pids[0]==0) 
    { 
     fprintf(stdout, "PID=%d PRODUCER\n", getpid()); 
     close(fd[0]); //produttore 
     sleep(3); 
     fprintf(stdout, "Insert strings (max 30 chars), finish with 'end':\n"); 
     fscanf(stdin, "%s", string); 
     while(1) 
     { 
      if(strcmp(tmp, "end")==0) 
     break; 
      l=strlen(string)+1; 
      sprintf(tmp, "%2lu%s", l, string); 
      printf("%s\n", tmp); 
      nW=write(fd[1], tmp, (l+2)); 
      printf("nW(PRODUCER)=%d", nW); 
      if(nW!=(l+2)) 
     { 
      perror("wrote not whole string"); 
      exit(1); 
     } 
      sleep(5); 
      kill(pids[1], SIGUSR1); 
      pause(); 
      fprintf(stdout, "Insert string:\n"); 
      fscanf(stdin, "%s", string); 
     } 

     exit(0); 
    } 
     pids[1]=fork(); 
     if(pids[1]==0) 
    { 
     fprintf(stdout, "PID=%d CONSUMER\n", getpid()); 
     close(fd[0]); //consumer 

     while(1) 
     { 
      pause(); 
      read(fd[0], tmp, MAXC+1); 
      printf("tmp(CONSUMER)=%s\n", tmp); 
      sscanf(tmp, "%2lu%s", &l, stringtoup); 
      printf("lenght string(CONSUMER)=%2lu\n", l); 
      printf("stringtoup=%s\n", stringtoup); 
      for(i=0; i<l; i++) 
     stringtoup[i]=toupper(stringtoup[i]); 

      fprintf(stdout, "%s\n", stringtoup); 
      fflush(stdout); 
      sleep(1); 
      kill(pids[0], SIGUSR1); 
     } 
     exit(0); 
    } 

     sleep(4); 
     for(i=0; i<2; i++) 
    { 
     waitpid(pids[i], NULL, 0); 
     fprintf(stdout, "PID=%d exited\n", pids[i]); 
    } 

    } 
    return(0); 
} 

редактировать: код фиксированной

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <fcntl.h> 
#include <ctype.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/wait.h> 
#define MAXC 30 

pid_t pids[2]; 
int main() 
{ 
    int fd[2], i, nW; 
    size_t l; 
    char string[MAXC+1], stringtoup[MAXC+1], tmp[MAXC+1]; 

    if(pipe(fd)==0) 
    {  
     pids[0]=fork(); 
     if(pids[0]==0) 
    { 
     fprintf(stdout, "PID=%d PRODUCER\n", getpid()); 
     close(fd[0]); //produttore 
     fprintf(stdout, "Insert strings (max 30 chars), finish with 'end':\n"); 
     fscanf(stdin, "%s", string); 
     while(1) 
     { 
      if(strcmp(string, "end")==0) 
     break; 
      l=strlen(string)+1; 
      sprintf(tmp, "%2lu%s", l, string); 
      nW=write(fd[1], tmp, (l+2)); 
      if(nW!=(l+2)) 
     { 
      perror("wrote not whole string"); 
      exit(1); 
     } 
      sleep(1); 

      fscanf(stdin, "%s", string); 
     } 
     kill(pids[1], SIGINT); 
     exit(0); 
    } 
     pids[1]=fork(); 
     if(pids[1]==0) 
    { 
     fprintf(stdout, "PID=%d CONSUMER\n", getpid()); 
     close(fd[1]); //consumer 

     while(1) 
     { 
      read(fd[0], tmp, MAXC+1); 
      sscanf(tmp, "%2lu%s", &l, stringtoup); 
      for(i=0; i<l; i++) 
     stringtoup[i]=toupper(stringtoup[i]); 

      fprintf(stdout, "%s\n", stringtoup); 
      fflush(stdout); 
      sleep(1); 
     } 
     exit(0); 
    } 

     for(i=0; i<2; i++) 
    { 
     waitpid(pids[i], NULL, 0); 
     fprintf(stdout, "PID=%d exited\n", pids[i]); 
    } 
    } 
    return(0); 
} 
+2

Учитывая, что вы не показываете какой-либо код, какой ответ вы ожидаете? Чтобы включить код в свой вопрос, просто отредактируйте его, добавьте код и нажмите Ctrl-K, чтобы добавить форматирование кода. –

+0

Готово. Спасибо вам за помощь! – Zanarkand

+0

В 'close (fd [0]); // consumer' должно быть 'fd [1]'. – user58697

ответ

2

Прочитав комментарии, я думаю, что вопрос изменен и касается процедуры kill-wait.

Проблема должна заключаться в том, что дети не имеют ничего общего с памятью родителей с момента их раздвоения.

Первый ребенок (производитель) имеет pids массив, заполненный, как:

pids[0] == 0; 
pids[1] == undefined; 

Значение pids[1] никогда не меняется, как этот процесс никогда не меняет ту часть своей собственной памяти.

Второго ребенок (потребитель) имеет pids массив, заполненный, как:

pids[0] == first_child's pid; 
pids[1] == 0; 

В целом, только родитель может убить второй ребенок (один с pids[1]), а не первым ребенком. Таким образом, «производитель» убивает процесс с помощью какого-то pid, которого вы не знаете (что может вызвать более сложную системную проблему, если не повезет), поэтому «потребитель» никогда не получает ее.

Если на трубе нет писателей, функция read() возвращает ноль (0). Это то, что вы должны использовать, сломать, когда это произойдет и выйти. С другой стороны, когда есть писатели, функциональные блоки read() блокируются, пока не будет чего-то читать, поэтому sleep(1) не требуется.

Как я вижу, программа не работает правильно, когда происходит убийство этого случайного процесса, и поэтому родитель не печатает выход любого ребенка. Однако, если вы удалите это kill(...), закройте конец письма и проверьте возвращаемое значение read(...), программа работает так, как должна.

Кроме того, хороший шаблон для закрытия всех fds, которые вам не нужны (даже если функция выхода сделает это в какой-то момент), поэтому родитель сразу после того, как породил всех детей, мог закрыть 2 fds (это должен закрыть конец записи для разрыва читателя!), и читатель может закрыть оставшуюся fd перед выходом. Ниже приведены части кода, которые необходимо устранить.

... 
if(pids[0]==0)     
      {           
        fprintf(stdout, "PID=%d PRODUCER\n", getpid()); 
        close(fd[0]); //produttore        
        fprintf(stdout, "Insert strings (max 30 chars), finish with 'end':\n"); 
        fscanf(stdin, "%s", string);           
        while(1)                 
        {                       
          if(strcmp(string, "end")==0)                   
            break;                          
          l=strlen(string)+1;                       
          sprintf(tmp, "%2lu%s", l, string);                      
          nW=write(fd[1], tmp, (l+2));                          
          if(nW!=(l+2))                                
          {                                       
            perror("wrote not whole string");                                           exit(1); 
          }                                                   sleep(1); 
                                                             fscanf(stdin, "%s", string); 
        }                                        
        close(fd[1]); 
        exit(0); 
      } 
      pids[1]=fork(); 
      if(pids[1]==0) 
      {    
        fprintf(stdout, "PID=%d CONSUMER\n", getpid());           
        close(fd[1]); //consumer  

        while(1)           
        {                
          if (read(fd[0], tmp, MAXC+1) == 0) 
            break; 
          sscanf(tmp, "%2lu%s", &l, stringtoup); 
          for(i=0; i<l; i++)             
            stringtoup[i]=toupper(stringtoup[i]);          

          fprintf(stdout, "%s\n", stringtoup); 
          fflush(stdout); 
          sleep(1); // this could be removed 
        } 
        close(fd[0]); 
        exit(0); 
      } 

      close(fd[0]); 
      close(fd[1]); 
      for(i=0; i<2; i++) 
...