从管道读取错误

时间:2010-08-10 19:16:26

标签: c process pipe

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]);
  }
   }

当我从管道功能写入God函数到Turtle函数时。我希望它在用户没有输入时返回任何内容,而在用户给出任何输入时返回数字。但是printf语句正在打印输出,如

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

在我看来,这个数字的内存地址。我在程序中犯的错误是什么。

3 个答案:

答案 0 :(得分:3)

关于您的计划的几点意见:

在功能turtle中:

  1. 您没有初始化变量msg
  2. 您为gtot设置了O_NONBLOCK文件描述符。
  3. 但是你没有检查read
  4. 的返回值

    这是一个重大问题。 read立即返回,您正在打印未初始化的msg值。

    • forkclose的方式也有所贡献。您已在gtot[1]之前关闭fork - “神”过程。如果您选择使用这种双子进程的单亲方法,那么在完成close之前,不要fork文件处理。

    • 此外,您似乎打算至少使用turtle函数,可能还有god函数来循环。如上所述,您的乌龟函数将立即退出:它没有循环,并且在设置read标志的情况下执行O_NONBLOCK

    • 但等等,还有更多。当您致电fcntl设置O_NONBLOCK时,您正在执行的操作也会重置O_NONBLOCK以外的每个标记。这是一个取自the libc documentation的函数,它在设置或重置非阻塞标志时处理其他标志:

    / *如果值为非零,则设置desc的O_NONBLOCK标志,    如果值为0,则清除该标志。    成功时返回0,如果设置了errno,则返回-1。 * /

    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);
    }
    

    还有一些其他因素也可能导致您的问题:

    • 最好在4sizeof(int)的任何地方,用read替换“write”的每一次出现。您的机器上的整数可能是8个字节(64位整数?),尽管不太可能。将来,int更有可能是8个字节,而且您的代码在这方面非常脆弱。

    我正在观察的节目中还有一些“奇怪的”:

    • 为什么printf的十进制输出前缀为0(零)?这将是八进制表示,但printf说明符不是"%o""%d"不应显示前导零,除非您使用带前导零的宽度说明符,即"%08d"。所以我不知道该怎么做。

答案 1 :(得分:2)

你不想两次打电话给叉子。 您也不想关闭管道的未使用端:)

答案 2 :(得分:1)

如果这是Linux,请尝试使用strace查看写入管道的确切数据。

如果是Solaris或Mac OS X,请尝试dtrace或dtruss。

在BSD上我相信查看系统调用的命令只是桁架。

这些非常有用的命令。