epoll/poll/epoll & 高级IO详解

五种IO模型

阻塞IO

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

非阻塞IO

  • 非阻塞IO:如果内核的还未将数据准备好,系统调用仍然会直接返回,并且返回EWOULDBLOCK错误码
  • 非阻塞IO往往需要程序员循环的方式反复尝试读写文件描述符,这个过程称为轮询,这对CPU来说是较大的浪费,只有特定的场景下才使用。

信号驱动

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

IO多路转接

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

异步IO

  • 异步IO:由内核在数据拷贝完成时,通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据),不需要自己主动获取
  • 任何IO过程,都包含两个步骤,第一是等待,第二是拷贝,而且在实际的应用场景中,等待消耗的时间玩往往高于拷贝的时间,让IO更高效,最核心的办法就是让等待的时间尽量少

钓鱼

  • 阻塞
  • 非阻塞:钓鱼的时候玩玩手机,再看看鱼
  • 信号:鱼缸上绑铃铛,铃铛响了了
  • IO多路转接:阻塞的,扎了一排鱼杆,一眼不眨的等鱼
  • 异步IO:鱼竿是自动的,可以自己钓鱼,鱼钓上来就通知

高级IO的重要概念

同步通信和异步通信

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

  • 所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不反悔,但是一旦返回,就得到了返回值了,换句话说,就是由调用者主动等待这个调用过程
  • 异步则相反,调用在出发之后,这个调用就直接返回了,所以没有返回结果,换句话说,当一个异步过程调用出发后,调用者不会立刻得到结果,而是在调用出发后,被调用者通过状态,通知调用者,或通过回调函数处理这个调用
  • 这里的同步和多线程的同步和互斥中的同步不是一个东西,不要混淆
  • 例如epoll的回调函数机制,通过回调函数来直接修改数组中的标记,调用epoll不需要返回结果,这个场景就是异步。

例如

假设你去吃饭,点了一个炒菜
(1)同步就是你点饭后,一直在那里等着厨师给你做,直到厨师做完,你自己把饭端走,即就是说结果由你自己主动获取
(2)异步,就是点饭之后,去找一个位置作者,当服务员告诉你的饭做好了,你去把饭端过来,即就是说,结果由服务员通知你,你自己使被动的得知调用结果,如果服务员不通知,你是不知道结果的
  • 在于这个结果你是怎么知道的
  • 是主动的还是被动的知道的

阻塞和非阻塞

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

  • 阻塞调用是指调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回
  • 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程
  • 关注调用函数的时候是否阻塞

同步阻塞

  • 调用结果由调用者主动获取,且是阻塞式的等待,即调用者会主动的关注调用结果,一直在那看着

同步非阻塞

  • 调用结果是由调用者主动获取,但是是非阻塞的等着,轮询的方式,时不时回来看一下执行的结果。

异步阻塞

  • 调用结果是被调用者通知给调用者的,而且是阻塞式的在哪里等着,并且自己不光等着,也不会看执行得怎么样了,而是等待被调用者的通知

异步非阻塞I

  • 调用结果是由被调用者通知给调用者就行了,调用者自己可以去干其他事,不需要主动的获取结果,同时自己也不会被阻塞。

等女朋友的例子:

同步阻塞

  • 等女朋友,单纯的等,啥都不干,就一直看着她有没有做完事
    同步非阻塞
  • 等女朋友的时候还一般等一边打游戏,打会游戏然后看看她做完事没
    异步阻塞
  • 等女朋友,然后什么也不做,就一直等,但是也不会关注她什么时候收拾好,等她收拾好了会主动通知你,然后你就知道她收拾好了
    异步非阻塞
  • 等女朋友,然后你还边敲代码,你也不用去关注她收拾好没,她会主动通知你,然后你就知道她完事了

fcntl

  • 一个文件描述符,默认都是阻塞IO,fcntl有能力让阻塞变成阻塞
函数原型
#include <unistd>
#include <fcntl.h>
int fcntl(int fd,int cmd,.../*arg*/);

根据传入的cmd值不同,后面追加的参数也不相同
,fcntl函数有五种功能

  • 复制一个现有的文件描述符 (cmd = F_DUPFD)
  • 获得/设置文件描述符标记 (cmd = F_GETFD 或 F_SETFD)
  • 获得/设置文件状态标记 (cmd = F_GETFL或 F_SETEL)
  • 获得/设置异步I/O所有权 (cmd = F_GETOWN或F_SETOWN)
  • 获得/设置记录锁 (cmd = F_GETLK,F_SETLK 或 F_SETLKW)

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

基于fcntl实现一个SetNoBlock函数
//传入文件描述符
void SetNoBlock(int fd)
{ 
  //保存修改前的状态信息(一个位图)
  int f1 = fcntl(fd,F_GETFL);//get file
  if(f1<0)
  {
    cerr<<"fcntl"<<endl;
    return;
  }
  //将文件描述符设置为非阻塞
  fcntl(fd,F_SETFL,f1|O_NONBLOCK);//set file
}

select

  • select系统调用是让我们的程序监控多个文件描述符的状态变化的
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
select、pollepoll都是I/O多路复用机制,用于同时监听多个I/O事件的状态。它们的基本原理是通过查询所有socket连接,如果有数据到达,就通知用户进程。\[2\]这些机制都属于同步I/O,需要在事件就绪后自己负责读写,并且读写过程会阻塞。而异步I/O则不会自己读写和阻塞,而是负责将数据从内核拷贝到用户空间。\[3\] select是最早出现的I/O多路复用机制,它使用fd_set数据结构来存储需要监听的文件描述符,通过调用select函数来等待事件的发生。select的缺点是效率较低,因为每次调用select都需要将所有的文件描述符集合传递给内核,而且select的文件描述符数量有限制。\[1\] poll是select的改进版本,它使用pollfd数据结构来存储需要监听的文件描述符,通过调用poll函数来等待事件的发生。poll相对于select的优点是没有文件描述符数量的限制,但仍然需要将所有的文件描述符集合传递给内核。\[1\] epoll是Linux特有的I/O多路复用机制,它使用epoll_event数据结构来存储需要监听的文件描述符,通过调用epoll_ctl函数来注册事件,然后通过调用epoll_wait函数来等待事件的发生。epoll的优点是没有文件描述符数量的限制,而且在注册事件时只需要拷贝一次文件描述符到内核,而不是在等待事件时重复拷贝。epoll还支持水平触发和边沿触发两种模式,边沿触发模式可以降低同一个事件被重复触发的次数。\[1\] 总结来说,select、pollepoll都是用于实现I/O多路复用的机制,它们的选择取决于具体的应用场景和需求。select适用于连接数量多但活动连接较少的情况,poll适用于连接数量多且活动连接较多的情况,而epoll适用于连接数量多但活动连接较少的情况,并且具有更高的效率和更灵活的触发模式。\[1\] #### 引用[.reference_title] - *1* *3* [select、pollepoll简介](https://blog.csdn.net/HuYingJie_1995/article/details/130516595)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [select、pollepoll详解](https://blog.csdn.net/ljjjjjjjjjjj/article/details/129720990)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值