计算机网络之五种IO模型与阻塞IO

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

计算机网络之五种IO模型与阻塞IO

收录于专栏【计算机网络
本专栏旨在分享学习计算机网络的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

五种IO模型

阻塞IO

非阻塞IO

信号驱动IO

IO多路转接

异步IO

高级IO重要概念

[同步通信 vs 异步通信](#同步通信 vs 异步通信)

[阻塞 vs 非阻塞](#阻塞 vs 非阻塞)

其他高级IO

非阻塞IO

fcntl

实现函数SetNoBlock

轮询方式读取标准输入


五种IO模型

阻塞IO

**阻塞IO:**在内核中将数据准备好之前,系统调用会一直等待所有的套接字,默认都是阻塞方式。

阻塞IO是最常见的IO模型。

非阻塞IO

非阻塞IO:如果内核还未将数据准备好,系统调用仍然会直接返回,并且返回 EWOULDBLOCK 错误码。

非阻塞 IO 往往需要程序员循环的方式反复尝试读写文件描述符,这个过程称为轮询,这对 CPU 来说是较大的浪费,一般只有特定场景才使用。

信号驱动IO

信号驱动 IO:内核将数据准备好的时候,使用 SIGIO 信号通知应用程序进行 IO

IO多路转接

IO 多路转接:虽然从流程图上看起来和阻塞 IO 类似,实际上最核心在于 IO 多路转接能够同时等待多个文件描述符的就绪状态。

异步IO

异步 IO:由内核在数据拷贝完成时,通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据)。

高级IO重要概念

这里需要强调几个重要的概念。

同步通信 vs 异步通信

同步和异步关注的是消息通信机制。

所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了;换句话说,就是由调用者主动等待这个调用的结果。

异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果;换句话说,当一个异步过程调用发出后,调用者不会立即得到结果;而是在调用发出后,被调用者通过状态、通知来通知者,或通过回调函数处理这个调用。

另外,我们回忆在多进程多线程的时候,也提到同步和互斥,这里的同步通信和进程之间的同步时完全不相干的该概念。

进程/线程同步也是进程/线程之间直接的制约关系

是为完成某种任务而建立的两个或多个线程,这个线程需要在某些位置上的协调他们的工作次序而等待、传递信息所产生的制约关系。尤其是在访问临界资源的时候。

在看到同步这个词,一定要搞清楚大背景是什么,这个同步,是同步通信异步通信的同步,还是同步或互斥的同步。

阻塞 vs 非阻塞

阻塞和非阻塞关注的是程序员在等待调用的结果(消息,返回值)时的状态。

阻塞调用是调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回。

非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

其他高级IO

非阻塞 IO,记录锁,系统 V 流机制,I/O 多路转接(也叫 I/O 多路复用),readv 和 writev 函数以及存储映射 IO (mmap),这些统称为高级 IO。

后面我会重点介绍 I/O 多路转接

非阻塞IO

fcntl

一个文件描述符,默认都是阻塞 IO。

函数原型如下:

cpp 复制代码
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

传入的 cmd 的值不同,后面追加的参数也不相同。

fcntl 函数有5中功能:

复制一个现有的描述符 (cmd=F_DUPFD) 。

获得/设置文件描述符标记(cmd=F_GETFD 或 F_SETFD)。

获得/设置文件状态标记 (cmd=F_GETFL 或 F_SETFD)。

获得/设置异步 I/O 所有权 (cmd=F_GETOWN 或 F_SETOWN)。

获得/设置记录锁(cmd=F_GETLK,F_SETLK 或 F_SETLKW)。

我们此处只是使用第三种功能,获取/设置文件状态标记,就可以将一个文件描述符设置为非阻塞。

实现函数SetNoBlock

基于 fcntl,我们实现一个 SetNoBlock 函数,将文件描述符设置为非阻塞。

cpp 复制代码
void SetNoBlock(int fd)
{
    int fl = fcntl(fd, F_GETFL);
    if (fl < 0)
    {
        perror("fcntl");
        return;
    }
    fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}

使用 F_GETFL 将当前的文件描述符的属性取出来 (这是一个位图)。

然后再使用 F_SETFL 将文件描述符设置回去,设置回去的同时,加上一个 O_NONBLOCK 参数。

轮询方式读取标准输入

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
void SetNoBlock(int fd)
{
    int fl = fcntl(fd, F_GETFL);
    if (fl < 0)
    {
        perror("fcntl");
        return;
    }
    fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}
int main()
{
    SetNoBlock(0);
    while (1)
    {
        char buf[1024] = {0};
        ssize_t read_size = read(0, buf, sizeof(buf) - 1);
        if (read_size < 0)
        {
            perror("read");
            sleep(1);
            continue;
        }
        printf("input:%s\n", buf);
    }
    return 0;
}
相关推荐
FreeBuf_2 小时前
最新研究揭示云端大语言模型防护机制的成效与缺陷
网络·安全·语言模型
南郁6 小时前
007-nlohmann/json 项目应用-C++开源库108杰
c++·开源·json·nlohmann·现代c++·d2school·108杰
网硕互联的小客服7 小时前
如何利用Elastic Stack(ELK)进行安全日志分析
linux·服务器·网络·安全
浩浩测试一下7 小时前
Authpf(OpenBSD)认证防火墙到ssh连接到SSH端口转发技术栈 与渗透网络安全的关联 (RED Team Technique )
网络·网络协议·tcp/ip·安全·网络安全·php
菠萝017 小时前
共识算法Raft系列(1)——什么是Raft?
c++·后端·算法·区块链·共识算法
海棠蚀omo8 小时前
C++笔记-C++11(一)
开发语言·c++·笔记
leagsoft_10038 小时前
联软NSPM自动化策略管理 助力上交所加速国产化替代提升运维效率
运维·网络·自动化
孤寂大仙v8 小时前
【计算机网络】网络层IP协议与子网划分详解:从主机通信到网络设计的底层逻辑
tcp/ip·计算机网络·php
凌佚8 小时前
rknn优化教程(一)
c++·目标检测·性能优化
Think Spatial 空间思维9 小时前
【实施指南】Android客户端HTTPS双向认证实施指南
android·网络协议·https·ssl