Ошибка чтения из канала - PullRequest
       10

Ошибка чтения из канала

1 голос
/ 10 августа 2010
void turtle (int gtot)
{
    int msg;
    fcntl(gtot,F_SETFL,O_NONBLOCK);
    read(gtot,&msg,4);

    gotoxy(12, 21); printf("The value of buffer for turtle is %d",msg);

    //react to god's message
    xcoor += msg;
    msg = 0;
            sleep(sleep_time);
 }

 void god (int gtot )
 {
        char choice, sign;
        int distance;
        scanf("%c",&choice);
        //choice = getchar();
        gotoxy(1,18);
        printf("Enter the distance which should be moved");
        fflush(stdout);
        gotoxy(50, 14);
        scanf ("%d", &distance);
        int newd = distance;
        //printf ("The distance that is to be moved by %d", distance);

        if (choice == 'h')
        {
            write(gtoh,&distance,4);
        }
        else if (choice == 't')
        {
            write(gtot,&newd,4);
            gotoxy(12,23);
                            printf("I am writing %d as the number", distance); 
                            fflush(stdout);
        }
        //printf("You chose %s", &choice);
        sleep(sleep_time);
    }
    main(){
int gtot[2];
pipe (gtot);
pid_turtle = fork ();
if (pid_turtle == 0)
  {
      close (gtot[1]);
      turtle (gtot[0]);
  }

pid_god = fork ();
if (pid_god == 0)
  {
      close (gtot[0]);
      god (gtot[1]);
  }
   }

Когда я пишу из трубы из функции Бога в функцию Черепахи.Я ожидаю, что он ничего не выдаст, когда пользователь не вводит, и числа, когда пользователь дает какие-либо.Но оператор printf печатает выходные данные вроде

       The value of buffer for turtle is 0106368
       The value of buffer for turtle is 05291328

, что мне кажется адресом памяти числа.Какую ошибку я делаю в программе.

Ответы [ 3 ]

3 голосов
/ 10 августа 2010

Несколько замечаний о вашей программе:

В функции turtle:

  1. Вы не инициализируете переменную msg.
  2. Вы установили дескриптор файла gtot для O_NONBLOCK.
  3. НО вы не проверяете возвращаемое значение read.

Это серьезная проблема. read возвращается немедленно, и вы печатаете неинициализированное значение msg.

  • Способ, которым вы fork и close также вносите свой вклад. Вы закрыли gtot[1] до fork -го процесса "бога". Если вы решите использовать этот метод с одним родителем для процессов с двумя дочерними процессами, не close файл обрабатывает, пока вы не выполните fork -ing.

  • Кроме того, похоже, что вы намеревались выполнить по крайней мере функцию turtle и, вероятно, функцию god для цикла. Как написано, ваша функция черепахи немедленно завершится: у нее нет петли, и она выполняет read с установленным флагом O_NONBLOCK.

  • Но подождите, это еще не все. Когда вы вызываете fcntl для установки O_NONBLOCK, то, что вы делаете, также сбрасывает каждый флаг, кроме O_NONBLOCK. Вот функция, взятая из документации libc , которая обрабатывает другие флаги при установке или сбросе неблокирующего флага:

/ * Установить флаг O_NONBLOCK для desc, если значение отлично от нуля, или сбросьте флаг, если значение равно 0. Возвращает 0 в случае успеха или -1 в случае ошибки, если установлено значение errno. * /

int
set_nonblock_flag (int desc, int value)
{
  int oldflags = fcntl (desc, F_GETFL, 0);
  /* If reading the flags failed, return error indication now. */
  if (oldflags == -1)
    return -1;
  /* Set just the flag we want to set. */
  if (value != 0)
    oldflags |= O_NONBLOCK;
  else
    oldflags &= ~O_NONBLOCK;
  /* Store modified flag word in the descriptor. */
  return fcntl (desc, F_SETFL, oldflags);
}

Есть и другие вещи, которые также могут способствовать вашей проблеме:

  • Было бы лучше заменить каждый случай "4" на sizeof(int), куда бы вы ни звонили read и write. Возможно, что целые числа составляют 8 байт на вашем компьютере (64-разрядное целое число?), Хотя это довольно маловероятно. В будущем, более вероятно, что int будет 8 байтов, и ваш код очень хрупок в этом отношении.

В вашей программе есть что-то «странное», которое я наблюдаю:

  • Почему десятичный вывод из printf начинается с префикса 0 (ноль)? Это было бы восьмеричное представление, но спецификатор printf не является "%o". "%d" не должен показывать начальные нули, если вы не используете спецификатор ширины с начальным нулем, как "%08d". Так что я не знаю, что с этим делать.
2 голосов
/ 10 августа 2010

Вы не хотите дважды вызывать форк.Вы также не хотите закрывать неиспользуемые концы трубы:)

1 голос
/ 10 августа 2010

Если это Linux, попробуйте использовать strace, чтобы увидеть точные данные, записываемые в каналы.

Если это Solaris или Mac OS X, попробуйте dtrace или dtruss.

Я полагаю, что в BSDкоманда для просмотра системных вызовов - это просто ферма.

Это очень полезных команд.

...