只读方式打开文件和可读可写打开对select的影响

只读方式打开文件和可读可写打开对select的影响



https://img1.sycdn.imooc.com//climg/636b55fa09e7034914160439.jpg

为什么O_RDONLY方式打开的文件 和O_RDWR方式都是读管道文件 一个可以返回wait....一个却没有为什么?

下面是代码


// 使用 select 监听有名管道,当有名管道有数据时,读取数据并打印


#include <stdio.h>

#include <stdlib.h>

#include <sys/select.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <string.h>


#define FIFO_NAME "./fifo"



int main(void)

{

    int ret,frd;

    fd_set readfds,tmpfds;  

    struct timeval tv = {3,0},tmp_tv;

    char buffer[64] = {0};

    frd = open(FIFO_NAME,O_RDONLY);

    FD_ZERO(&readfds);  

    FD_ZERO(&tmpfds);  

    FD_SET(frd,&readfds);

   

    for(;;){

        tmp_tv = tv;    

        tmpfds = readfds;  

     

        ret = select(frd+1,&tmpfds,NULL,NULL,&tmp_tv);

        sleep(1);

        if (ret  == -1){

            perror("[ERROR] select(): ");

            exit(EXIT_FAILURE);

        }else if(ret==0){

          printf("waiting...\n");

        }else if (ret > 0){

          if (FD_ISSET(frd,&tmpfds)){  // 判断是否在集合中

              memset(buffer,0,sizeof(buffer));

              ret=read(frd,buffer,sizeof(buffer));

              if (frd== -1){

                perror("[ERROR] dest fopen(): ");

                close(frd);

                return -1;

              }

              printf("%s",buffer);

          }

        }

    }  

    close(frd);

    return 0;

}




正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
山行老师 2022-11-09 16:26:46

重新解释一下,管道本身带有阻塞的属性,阻塞有两个前提:
1)管道文件不能以O_RDWR方式打开,那样的话会失去阻塞属性,自己写自己读那就不需要阻塞;
2)在1的前提下,管道文件以O_RDONLY方式打开且没有数据会导致函数read()阻塞;
既然你这里用了select( ),目标就是非阻塞方式监听多个文件的可读事件。所以不应该让管道文件frd阻塞,要么使用O_RDWR打开,要么使用O_RDONLY|O_NONBLOCK打开。建议使用后者,更符合实际项目。
换句话说如果你让frd带上了阻塞属性,那么select( )内部探测frd是不是可读的时候就已经阻塞了,配置的第4参数就没有超时效果了,管道又没有数据,函数select( )自然就不会超时返回了,也就不会有超时打印wait...。

顺带说一下,函数select( )的第4个参数就是超时控制的,不需要后面跟一个sleep(1)。

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师