认识 fcntl 接口函数(文件非阻塞设置)

目录

一、fcntl函数的作用

二、fcntl 函数的声明

1、参数解析 

2、返回值解析

三、使用fcntl 将文件描述符设置为非阻塞

1、设置非阻塞模式实现

2、代码测试


一、fcntl函数的作用

read函数是典型的阻塞模型,当缓冲区里的数据不就绪的时候,会一直阻塞等待。这是正常的,因为文件描述符默认是阻塞IO,而我们可以通过 fcntl 接口函数将文件描述符设置为非阻塞IO。

设置成非阻塞IO以后,read函数会一直检测数据是否就绪,如果就绪就读取,并返回读取到的字符数;如果不就绪,就返回一个错误码。

二、fcntl 函数的声明

fcntl 函数的作用是操作一个文件的文件描述符,而设置成非阻塞IO只是 fcntl 函数的功能之一。

1、参数解析 

第一个参数fd,指明你要操作哪个文件的文件描述符。

第二个参数cmd,也就是你要对该文件描述符进行何种操作。cmd的取值不同,后面追加的参数也不同。

cmd的取值命令解析
F_DUPFD复制一个现有的文件描述符
F_GETFD 或 F_SETFD获得/设置文件描述符标记
F_GETFL 或 F_SETFL获得/设置文件状态标记
F_GETOWN 或 F_SETOWN获得/设置异步IO所有权
F_GETLK 或 F_SETLK( F_SETLKW )获得/设置记录锁

2、返回值解析

执行成功时,不同的cmd可能会对应不同的返回值,没有列举在下面的,比如F_SETFL,可能返回值类型为void。

执行出错时,也会有不同的返回值,此时可能就与cmd无关了。

三、使用fcntl 将文件描述符设置为非阻塞

1、设置非阻塞模式实现

以设置文件描述符为 0 的文件为例,将文件描述符设置为非阻塞状态,需要用到上述表格的第三个功能,获得/设置文件状态标记。基本思路为:第一步,先获取到原有的文件状态;第二步,在原有的基础上追加一种非阻塞状态。

void setNonBlock(){
    int fl = fcntl(0,F_GETFL);      //获取文件描述符为0的文件状态
    if (fl < 0)
    {
        perror("fcntl");
        return;
    }

    fcntl(0, F_SETFL, fl | O_NONBLOCK); //追加文件描述符的状态为非阻塞 
}

2、代码测试

函数准备好以后,在调用read函数之前先将 第0号文件描述符设置成非阻塞,然后再调用read函数。

int main(){
    setNonBlock();     //设置为非阻塞模式

    while (1)
    {
        char buffer[1024];
        ssize_t s = read(0,buffer,sizeof(buffer)-1);        //非阻塞读取
        if (s > 0)
        {
            buffer[s] = 0;
            write(1,buffer,s);        //将读取到的内容打印到屏幕上
            printf("read success, res: %d, content: %s\n",s, buffer);
        }
        else{
            if(errno == EAGAIN || errno == EWOULDBLOCK){
                printf("read failed, res: %d , errno: %d\n", s , errno);
            }
        }

        sleep(2);    
    }
    
    return 0;
}

测试结果如下,非阻塞模式下,read函数如果发现数据尚未就绪,系统是以出错的形式返回的,很显然数据未就绪不算错误,那么要如何区分真正的错误 和 数据未就绪时的出错呢?

答案是errno,errno是错误码,正常情况下是0。当数据没有就绪的时候,errno的值是11,即EAGAIN 或者 EWOULDBLOCK,我们可以以此判断是否真的出错了。如果你在成功时打印errno,你会发现errno仍然是11,因为read读取到数据的时候,不会设置errno。

read函数里有对EAGAIN的解释,EAGAIN会出现在当某个文件描述符被设置成非阻塞的时候。

  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值