2010-08-10 151 views
1
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

有关程序的若干意见:

在功能turtle

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

这是一个重要的问题。 read正在返回并且您正在打印未初始化的值msg

  • forkclose也贡献的方式。您在fork之前关闭了gtot[1]--这是“上帝”过程。如果您选择使用这种双亲过程方法的单亲,则不要close文件处理,直到完成fork -ing。

  • 另外,看起来您至少打算使用turtle函数,可能还有god函数进行循环。正如所写,你的乌龟功能将立即退出:它没有循环,它执行read并设置了O_NONBLOCK标志。

  • 但是等等,还有更多。当您拨打fcntl来设置O_NONBLOCK时,您所做的还将重置除O_NONBLOCK以外的每个标志。

/*设置递减的O_NONBLOCK标志,如果值不为零, 或清除标志,如果值是:这里是从the libc documentation其处理其它标志而设置或复位非阻塞标志截取的功能0. 成功时返回0,或者错误时使用errno set返回-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); 
} 

有可能还可以促进你的问题的一些其他的东西:

  • 这将是最好的,以取代“4”与sizeof(int)每一次出现,无论你在呼唤readwrite 。您的机器上的整数可能是8个字节(64位整数?),尽管可能性不大。在将来,int更可能是8个字节,并且您的代码在这方面非常脆弱。

也有一些“奇怪”的有关程序的,我观察:

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

谢谢,初始化味精工作奇迹! – w2lame 2010-08-10 19:43:00

+0

很高兴听到它。合十礼。 – 2010-08-10 19:43:51

+0

并再次感谢您提供的其他建议。他们真的帮助了我的计划,也帮助了我。 :D – w2lame 2010-08-10 19:58:41

1

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

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

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

这些是有用的命令。

+0

非常感谢您的建议。 – w2lame 2010-08-11 21:25:48

2

你不想调用叉两次。 你也不想关闭管道的未使用的末端:)

+0

由于程序的性质,我应该拨4次拨号。但是,为什么我不应该关闭管道未使用的端点。我认为这是一个很好的做法:) – w2lame 2010-08-10 19:58:10