从管道读取时无限循环

时间:2014-11-01 00:53:20

标签: c

有人能告诉我为什么从管道读取时会出现无限循环?我不明白我做错了什么。 message是我在main top中定义的名称。 MESSAGE是我的结构名称。它甚至不打印出测试值。

if(manager_pid == 0)
{
    printf("Hello? \n");
    if(close(pipe1[READING]) != 0)
    {
        printf("Error in closing pipe1 \n");
    }
    if(close(pipe2[READING]) != 0)
    {
        printf("Error in closing pipe2 \n");
    }
    if(close(pipe3[WRITING]) != 0)
    {
        printf("Error in closing pipe \n");
    }
}
i = 0;
printf("work please \n");
//test_value = read(pipe3[READING], &boo, sizeof(echo));
//printf("test_value is %d \n", test_value);

while(i < 10)
{
    printf("In while \n");
    //printf("Hello?? \n");
    //test_value = read(pipe3[READING], &boo, sizeof(echo));
    //printf("test_value is %d \n", test_value);
    //printf("Entering infinite loop \n");
    //printf("i is %d \n", i);
    //nbytes = read(pipe3[0], array, 45);
    //printf("nbytes is %d \n", nbytes);
    //log_dat_fp = fopen(argv[2], "a");
    if(read(pipe3[READING], &message, sizeof(struct MESSAGE)) != -1)
    {
        printf("Entering if \n");
        log_dat_fp = fopen(argv[2], "a");
        printf("First if  \n");
        time(&current_time);
        //if(message.owner == 1 && (message.instruction == 'r' || message.instruction == 'R'))
        if(message.instruction == 'r' || message.instruction == 'R')
        {
            if(message.owner == 1)
            {
                printf("message.owner == 1 with r or R \n");
                fprintf(log_dat_fp, "Store Manager at time: %s received message %d %d %c %s", strtok(ctime(&current_time), "\n"), 
                message.owner, getpid(), message.instruction, message.id);
                pclose(log_dat_fp);
            }
            else if(message.owner == 2)
            {
                printf("message.owner == 2 with r or R  \n");
                fprintf(log_dat_fp, "Store Manager at time: %s received message %d %d %c %s", strtok(ctime(&current_time), "\n"), 
                message.owner, getpid(), message.instruction, message.id);
                pclose(log_dat_fp);
            }
            else
            {
                printf("You have junk  \n");
            }
        }
        else if(message.instruction == 'u' || message.instruction == 'U')
        {
            if(message.owner == 1)
            {
                printf("message.owner == 1 with u or U  \n");
                fprintf(log_dat_fp, "Store Manager at time: %s received message %d %d %c %s %d", strtok(ctime(&current_time), "\n"), 
                message.owner, getpid(), message.instruction, message.id, message.value);
                pclose(log_dat_fp);
            }
            else if(message.owner == 2)
            {
                printf("message.owner == 2 with u or U  \n");
                fprintf(log_dat_fp, "Store Manager at time: %s received message %d %d %c %s %d", strtok(ctime(&current_time), "\n"), 
                message.owner, getpid(), message.instruction, message.id, message.value);
                pclose(log_dat_fp);
            }
            else
            {
                printf("You have junk  \n");
            }
        }
        else
        {
            printf("manager can't read from pipe\n");
            exit(1);
        } // read no good
        if(message.instruction == 'r' || message.instruction == 'R')
        {
            if(message.owner == 1)
            {
                for(i = 0; i < 200; i++)
                {
                    if(strcmp(storage, table[i].id) == 0)
                    {
                        match_flag = 1;
                        value = table[i].value;
                    }
                }
                if(match_flag == 1)
                {
                    message.value = value;
                    message.owner = 0;
                    if(write(pipe1[WRITING], &message, sizeof(struct MESSAGE)) == sizeof(struct MESSAGE))
                    {
                        log_dat_fp = fopen(argv[2], "a");
                        time(&current_time);
                        fprintf(log_dat_fp, "Store Manager at time: %s sent message: %c %d %s %d\n", strtok(ctime(&current_time), "\n"), 
                        message.instruction, message.owner, message.id, message.value);
                        fclose(log_dat_fp);
                    }
                    else
                    {
                        printf("error returning message to process 1");
                        exit(1);
                    }
                }
                else
                    message.owner = 1;
                    if(write(pipe1[WRITING], &message, sizeof(struct MESSAGE)) == sizeof(struct MESSAGE))
                    {
                        log_dat_fp = fopen(argv[2], "a");
                        time(&current_time);
                        fprintf(log_dat_fp, "Store Manager at time: %s sent message: %c %d %s \n", strtok(ctime(&current_time), "\n"), 
                        message.instruction, message.owner, message.id);
                        fclose(log_dat_fp);
                    }

            }
            else if(message.owner == 2)
            {
                printf("message.owner == 2 with u or U  \n");
                fprintf(log_dat_fp, "Store Manager at time: %s received message %d %d %c %s %d", strtok(ctime(&current_time), "\n"), 
                message.owner, getpid(), message.instruction, message.id, message.value);
                pclose(log_dat_fp);
            }
            else
            {
                printf("You have junk  \n");
            }

        }
    }
    else
    {
        printf("manager had pipe issues.\n");
        exit(1);
    }// read no good
    i++;
    //log_dat_fp = fopen(argv[2], "a");
    printf("Each pass  \n");
}

1 个答案:

答案 0 :(得分:3)

POSIX read() 函数在EOF上返回0,而不是-1。由于您测试了错误的条件,因此您将获得无限循环。

请注意,说明如下:

  

尝试从空管道或FIFO读取时:

     
      
  • 如果没有进程打开管道进行写入,read()将返回0以指示文件结束。

  •   
  • 如果某个进程打开了管道并且设置了O_NONBLOCK,则read()将返回-1并将errno设置为[EAGAIN]

  •   
  • 如果某个进程打开了管道并且O_NONBLOCK已清除,read()将阻塞调用线程,直到写入某些数据或管道被所有具有该管道的进程关闭管道开放供写作。

  •   

读取零字节,因为没有要读取的字节是成功的。这就是read()指示EOF的方式,无论它是在文件上还是在任何其他设备类型上。终端是一个特例;键入后(在Unix上) control-D ,它们可能返回0个字节,然后重试可能会返回后面输入的额外数据。很久以前,磁带驱动器有点相似。但是当read()返回0时,(暂时)没有更多数据要读取。对于管道,这意味着所有编写器都关闭了它们的写文件描述符。