Проблема с простой трубной связью в C - PullRequest
0 голосов
/ 31 октября 2010

У меня проблема с этим упражнением:

Напишите программу на C, которая создает ребенка, а между отцом и ребенком будет двухсторонняя связь с использованием каналов. Его отец прочитал файл (имя которого будет указано пользователем) и пошлет письма ребенку.

Ребенок посчитает количество слов, начинающихся с с с 'a'; если число равно X слов X, начинающемуся с 'a', больше 5, то ребенок создаст своего собственного ребенка (внука). Внук истеблишмента отправит дедом * значение X число любым доступным вам способом и выйдет. [ Путем логического вывода: если число X меньше 6, тогда ребенок просто выходит, и «выход будет прародителем». ]

  • Примечание: дед = начальный процесс отца, этого отца внука отца

Вот что я сделал до сих пор; пожалуйста, помогите мне ...

#include <stdio.h>
#include<string.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc, char *argv[]) 
{ 
 int fd1[2], fd2[2], pid, status,sum=0, i;
 char gram[100], x;
 char buff[100];
 char rev[1000];
FILE *fp;
 if (pipe(fd1) == -1) { /* Create a pipe */
  perror("pipe");
  exit(1);
 }
 pid = fork();
 switch (pid)
  { 
 case -1:
  perror ("Fork error\n");
  exit(99); // in case of error
 case 0:
  close(fd1[1]);//Close the writing side 

  rev[1000]= read(fd1[0], buff, 1000); /* Read from the pipe */
  /*for (i=0; i< 1000 ; i++)
  {
   rev[i] = read(fd1[0], buff, sizeof(buff));
  }*/

   while( rev[i] != '\0')
   { 
    if (buff[i] == 'a' )
    {  sum++;
      i++;
    }  
    if (rev[i] == "")
    {

     if (rev[i+1]) //elenxei to epomeno tou kenou
     {
      sum++;
      i++;
     }
    }
    i++;
   }
   printf("%d", sum);

  exit(0);
 default:
  printf("dwse arxeio\n");
  scanf("%s", gram);
  close(fd1[0]);//Close the reading side
  fp = fopen (gram,"r"); 
  getc(fp);
  fclose(fp);
  write(fd1[1], buff, sizeof(buff)+1);
  close(fd1[1]);//Close the writing side
  wait(&status); // waits till the child process  ends
 } 
}

Ответы [ 3 ]

1 голос
/ 31 октября 2010

Давайте назовем три процесса: GP (для дедушки), PP (для родительского процесса) и GC (для внуков).В общих чертах, я думаю, что вам нужно сделать следующее:

  1. GP создает два канала (4 дескриптора файла) с обозначением RP (канал чтения) и WP (канал записи).Это описывает, как GP будет их использовать;PP и GC будут писать на RP и читать на WP.
  2. Форкс GP, создавая PP.
  3. GP закроет конец записи RP и конец чтения WP.
  4. GP откроет файл.
  5. GP запишет любое подмножество файла, подходящее для PP, через WP.
  6. GP закроет WP, когда больше нет данных для передачи.
  7. GP также должен закрыть файл, который он открыл.
  8. Затем GP будет читать из RP, возможно, сохраняя данные до тех пор, пока не получит EOF.
  9. Если получит какую-либо информацию обратно, GP выдаст эхоэта информация выводится на стандартный вывод.
  10. GP может прерваться.

Между тем, шаг 2 выше создал PP, который должен выполнить какую-то работу:

  1. PP должен закрыть конец чтения RP и конец записи WP.
  2. PP сидит в цикле, считывая данные из WP, считая все, что имеет отношение.
  3. Когда PP получает EOF наWP, он может решить, что ему нужно делать.
  4. PP теперь может закрыть конец чтения WP.
  5. Если его счетчик Xбольше 5, тогда (по причинам, которые имеют смысл только в домашней работе), он будет создан для создания GC;затем он может выйти.
  6. Если его счетчик X не достигает порогового значения, то, насколько указано в спецификации, он может немедленно завершиться.Для отладки вам, вероятно, придется распечатать что-то в stdout о том, что он сделал и почему.

Теперь у вас есть GP и GC;помните, что GC является почти точной копией PP, и (в частности) GC знает значение X точно так же, как и PP.Итак, GC также выполняет некоторую работу:

  1. GC форматирует X в виде строки (возможно - вы могли бы выполнять двоичную передачу данных, если хотите, но это передает баг форматирования GP, вот и все).
  2. GC записывает отформатированный X в конец записи RP.
  3. GC закрывает конец записи RP.
  4. GC выходит.

Шаг 3 GC гарантирует, что GP выйдет из своего шага 8.

С точки зрения промышленного образца, нет смысла создавать GC;ПП вполне может сделать то, что делает ГК.Как домашнее задание, оно проходит проверку.Ключевое понимание в комментариях выше:

Суть вопроса в том, как общаться от внука до дедушки.Хорошая новость заключается в том, что внук наследует открытые каналы в дочернем элементе.

Другими ключевыми шагами являются закрытие неиспользуемых концов каналов и закрытие каналов, когда больше нечего писать.Без этих закрытий процессы могут застрять в тупике.Например, если GP не удается закрыть конец записи RP, он никогда не получит EOF при чтении из RP, потому что есть процесс, который все еще может писать в RP - и этот процесс - GP!

1 голос
/ 31 октября 2010

Вы, вероятно, хотите посмотреть на popen . Он запускает дочерний процесс и возвращает ФАЙЛ *, который вы можете использовать для чтения / записи в дочерний стандарт / стандартный вывод.

0 голосов
/ 01 ноября 2010
rev[1000]= read(fd1[0], buff, 1000); /* Read from the pipe */

Что вы пытаетесь достичь с помощью lvalue здесь?

Во-первых, rev объявляется имеющим 1000 элементов, поэтому rev[1000] является переполнением буфера ...

Во-вторых, я предлагаю вам взглянуть на раздел «Возвращаемое значение» страницы руководства для read(). Он возвращает количество полученных байтов (которое может быть меньше указанного вами третьего параметра), либо 0 в конце файла, либо отрицательное при ошибке. Он заполнит содержимое buff фактическими данными. Из вашего кода я не уверен, что вы ожидаете, что системный вызов будет действовать, но мне не кажется, что вы используете его правильно.

Вы хотите сделать что-то вроде этого:

int r;

r = read(fd1[0], buff, sizeof(buff));
if (r < 0)       { /* TODO: Handle error */ }
else if (r == 0) { /* TODO: Handle EOF */ }
else             { /* TODO: Handle the fact that buff now contains 'r' bytes */ }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...