Linux:谈谈阻塞式和非阻塞式IO

文章目录

本篇总结的核心内容就是非阻塞式IO,直接看代码

阻塞式和非阻塞式IO

阻塞式IO

如下所示是典型的阻塞式IO

cpp 复制代码
#include <iostream>
#include <unistd.h>
using namespace std;

int main()
{
    char buff[1024];
    while(true)
    {
        ssize_t n = read(0, buff, sizeof(buff) - 1);
        // 如果接收成功
        if(n > 0)
        {
            buff[n - 1] = 0;
            cout << "buffer get : " << buff << endl;
        }
        // 如果结束
        else if(n == 0)
        {
            cout << "read done" << endl;
            break;
        }
        else
        {
            cerr << "read error" << endl;
            break;
        }
    }
    return 0;
}

非阻塞式IO

那如果今天我们想把他更换为非阻塞式IO呢?就要用到前面所说的一个fcntl函数了:

这个函数的第二个参数是一个标记位,里面包含的是众多的common选项,当它获取成功之后,回返回一个当前文件的一个老的标记位,而如果想要设置的话就可以用这个老的标记位按位与进去一个新的,这样就设置好了所谓的非阻塞式标记位,下面用代码来实现:

cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <cerrno>
#include <cstring>
using namespace std;

void SetNonblock(int fd)
{
    int fl = fcntl(fd, F_GETFL);
    if (fl < 0)
    {
        cerr << "fcntl" << endl;
        return;
    }
    fcntl(fd, F_SETFL, fl | O_NONBLOCK);
    cout << "set " << fd << " nonblock success" << endl;
}

int main()
{
    char buff[1024];
    SetNonblock(0);
    while (true)
    {
        ssize_t n = read(0, buff, sizeof(buff) - 1);
        // 如果接收成功
        if (n > 0)
        {
            buff[n - 1] = 0;
            cout << "buffer get : " << buff << endl;
        }
        // 如果结束
        else if (n == 0)
        {
            cout << "read done" << endl;
            break;
        }
        else
        {
            cerr << "read error"
                 << ", n : " << n << ", error : " << errno << " , strerror : " << strerror(errno) << endl;
            sleep(1);
        }
    }
    return 0;
}

由运行结果可以看出,直接运行失败了,返回值是-1,并且在错误码的信息中可以看到是资源没有就绪

上图所示的就是非阻塞式轮询了,由于用户输入的数据太慢了,所以在实际的查询中,绝大多数情况下都是查询不到消息的,而由此得出的一个重要结论是,如果被设置为非阻塞式轮询,那么如果底层的fd对应的数据没有就绪,那么像这样的recvfrom或者是read的接口,返回值就会以出错的形式进行返回

但是实际上,这真的出错了吗?答案必然是没有的,出错是分情况的,一种是真的出错了,比如这个文件描述符被关闭了,或者是其他的意外情况,但是也可能是因为资源没有就绪的情况,所以避免的方式就是通过error错误码来进行区分,由此可以看出的一点是,非阻塞式是会进行轮询的检查的,并且不会阻塞在这个函数这里,而是会一直的去检查对应的信息,如果资源没有就绪,还可以去做其他的事,等资源就绪了再进行一些其他的操作

阻塞式和非阻塞式IO整体来说比较简单,重点是下面的话题,多路转接

相关推荐
chlk1237 小时前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑8 小时前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件8 小时前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
碳基沙盒9 小时前
OpenClaw 多 Agent 配置实战指南
运维
深紫色的三北六号18 小时前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash1 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI1 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行2 天前
Linux和window共享文件夹
linux
Sinclair2 天前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器
木心月转码ing2 天前
WSL+Cpp开发环境配置
linux