什么是多路转接IO

对大量的描述符进行I/O事件监控—可以告诉进程现在有哪些描述符就绪了,然后进行就可以只针对就绪了的描述符进行响应操作,避免对没有就绪的I/O操作所导致的效率降低和流程阻塞

  • IO事件:可读事件/可写事件/异常事件

I/O多路转接模型之select

select介绍

系统提供select函数来实现多路复用输入/输出模型.

  • select系统调用是用来让我们的程序监视多个文件描述符的状态变化的;
  • 程序会停在select这里等待,直到被监视的文件描述符有一个或多个发生了状态改变

操作流程:

1.程序员定义某个事件的描述符集合(可读事件的描述符集合/可写事件的描述符集合/异常事件的描述符集合),初始化清空集合

对哪个描述符关心什么事件,就把这个描述符添加到相应时间的描述符集合中

2.发起监控调用,将集合拷贝到内核中进行监控,监控的原理原理是轮询遍历判断

可读事件的就绪:接收缓冲区中数据的大小低于水位标记(量化标准–通常默认为1个字节)
可写事件的就绪:发送缓冲区中剩余空间的大小大于低水位标记(量化标准—通常默认为1个字节)
异常事件的就绪:描述符是否产生了某个异常

3.监控的调用返回,表示监控出错/有描述符就绪/监控等待超时了

并且调用返回的时候,将事件监控的描述符集合中的未就绪描述符从集合中移除了----(集合中仅仅保留就绪的描述符
因为返回的时候修改了集合,因此下次监控的时候,就需要重新向集合中添加描述符

4.程序员轮询判断那个描述符仍然在哪个集合中,就确定这个描述符是否就绪了某个事件,然后进行对应事件的操作即可

select并不会直接返回给用户就绪的描述符,而是返回了就绪的描述符集合,因此需要程序员进行判断

代码操作:

1.定义集合—struct fd_set,成员只有一个数组(当做二进制位图使用)添加描述符就是将描述符对应的比特位置1

因此select能够监控的描述符数量,取决于二进制比特位多少,而比特位多少取决于宏 ,FD_SETSIZE,默认等于1024

void FD_ZERO(fd_set* set);//初始化清空集合
void FD_SET(int fd,fd_set* set);//将fd描述符添加到set集合中
  1. select开始调用监控
int select(int nfds,fd_set* readfds, fd_set* writefds, fd_set *exceptfds, struct timeval* timeout);
  • nfds:当前监控的集合中最大的描述符+1,减少遍历次数
  • readfds/writefds/exceptfds:可读/可写/异常三种事件的描述符集合
  • timeout:struct timeval{tv_sec;tv_usec};时间结构体,通过这个时间决定select阻塞/非阻塞/限制超时的阻塞

若timeout为NULL,则表示阻塞监控,直到描述符就绪/出错才会返回
若timeout中的成员数据为0,则表示阻塞,监控的时候若没有描述符就绪,则立即超时返回
若timeout中成员数据不为0,则在指定的时间内,没有就绪则超时返回

返回值:>0表示就绪的描述符个数
==0表示没有描述符就绪,超时返回
<0表示是监控出错

3.调用返回,返回给程序员,就绪的描述符集合,程序员遍历判断哪个描述符还在哪个集合中,就是就绪了那个事件

int FD_ISSET(int fd,fd_set *set);
//判断fd描述符是否在集合中

注意:因为select返回时会修改集合,因此每次监控的时候都要重新添加描述符

4.若对描述符不想进行监控了,则从集合中移除描述符

void FD_CLR(int fd,fd_set* set);//从描述符中删除描述符fd

select就绪条件

读就绪
  • socket内核中, 接收缓冲区中的字节数, 大于等于低水位标记SO_RCVLOWAT. 此时可以无阻塞的读该文件 描述符, 并且返回值大于0;
  • socket TCP通信中, 对端关闭连接, 此时对该socket读, 则返回0;
  • 监听的socket上有新的连接请求;
  • socket上有未处理的错误;
写就绪
  • socket内核中, 发送缓冲区中的可用字节数(发送缓冲区的空闲位置大小), 大于等于低水位标记 SO_SNDLOWAT, 此时可以无阻塞的写, 并且返回值大于0;
  • socket的写操作被关闭(close或者shutdown). 对一个写操作被关闭的socket进行写操作, 会触发SIGPIPE 信号;
  • socket使用非阻塞connect连接成功或失败之后;
  • socket上有未读取的错误;
异常就绪
  • socket上收到带外数据. 关于带外数据, 和TCP紧急模式相关(TCP协议头中, 有一个紧急指针的字段).

select优缺点分析

缺点
  1. select对描述符进行监控有最大数量上限,上限取决于宏-FD_SETSIZE,默认大小是1024
  2. 在内核中进行监控,是通过轮询遍历判断实现的,性能会随着描述符的增多而下降
  3. 只能返回就绪的集合,需要进程进行轮询遍历判断才能得知那个描述符就绪了哪个事件
  4. 每次监控都需要重新添加描述符到集合中,每次监控都需要将集合重新拷贝到内核中
优点:

遵循POSIX标准,跨平台移植性好

使用select简单检测标准输入

#include<sys/select.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/time.h>
#include<unistd.h>
#include<cstdio>
#include<time.h>
int main(int argc,char* argv[]){fd_set rfds;FD_ZERO(&rfds);//初始化描述符集合FD_SET(0,&rfds);//将描述符fd添加到描述符集合while(1){printf(">");fflush(stdout);int ret=select(1,&rfds,NULL,NULL,NULL);//监控if(ret<0){//监控错误perror("select error");continue;}if(FD_ISSET(0,&rfds)){//描述符已就绪char buf[1024];read(0,buf,sizeof(buf)-1);printf("buf-->%s\n",buf);}else{//描述符未就绪perror("error! invaild fd\n");continue;}FD_ZERO(&rfds);//将描述符置为0FD_SET(0,&rfds);//将标准输入描述符添加到集合中}return 0;
}

运行结果:

详解I/O多路转接之select相关推荐

  1. Linux下I/O多路转接之select --fd_set

    fd_set 你终于还是来了,能看到这个标题进来的,我想,你一定是和我遇到了一样的问题,一样的疑惑,接下来几个小时,我一定竭尽全力,写出我想说的,希望也正是你所需要的: 关于Linux下I/O多路转接 ...

  2. I/O多路转接之select

    I/O多路转接之select 文章目录 I/O多路转接之select 一.五种IO模型 二.I/O多路转接之select原理 一.五种IO模型 阻塞IO: 在内核将数据准备好之前, 系统调用会一直等待 ...

  3. I/O多路转接之 select

    系统提供select函数来实现多路复用输入/输出模型. 作用:select系统调用是用来让我们的程序监视多个文件句柄的状态变化的.程序会停在select这里等待,直到被监视的文件句柄有一个或多个发生了 ...

  4. Linux:I/O多路转接之select(有图有代码有真相!!!)

    一.select引入 一次 I/O 分为两个部分:1)等待数据就绪      2)进行数据转移 1.select 原理: select的原理就是减少等待数据就绪的比重,巧妙的利用等待队列机制让用户进程 ...

  5. 高级IO(多路转接之select、poll、epoll->核反应堆模式)

    ꧁ 大家好,我是 兔7 ,一位努力学习C++的博主~ ꧂ ☙ 如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步❧

  6. select poll epoll 高效IO 多路转接

    目录 五种常见IO模型 高效IO的概念 阻塞 vs 非阻塞 非阻塞IO fcntl函数 I/O多路转接之select 初识select select函数原型 select操作接口 tcp_server ...

  7. Python中的select、epoll详解

    Python中的select.epoll详解 文章目录 Python中的select.epoll详解 一.select 1.相关概念 2.select的特性 1.那么单进程是如何实现多并发的呢??? ...

  8. java爬取网页内容 简单例子(2)——附jsoup的select用法详解

    [背景] 在上一篇博文 java爬取网页内容 简单例子(1)--使用正则表达式 里面,介绍了如何使用正则表达式去解析网页的内容,虽然该正则表达式比较通用,但繁琐,代码量多,现实中想要想出一条简单的正则 ...

  9. IO多路转接 ——— select、poll、epoll

    文章目录 I/O多路转接之select select初识 select函数 socket就绪条件 select基本工作流程 select服务器 select的优点 select的缺点 select的适 ...

最新文章

  1. ubuntu14.04初体会
  2. 图解 Java 垃圾回收机制,写得非常好!
  3. python的head函数_python – 是否有一个pandas函数来显示第一个/最后一个n列,如.head().tail()?...
  4. php链接页面时加..,怎么给一个PHP密码访问页面加超链接
  5. Python 循环列表删除元素的注意事项
  6. Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)
  7. 【Python3爬虫】破解时光网登录加密参数并实现模拟登录
  8. php读取pdf文件乱码,使用php读取pdf文件
  9. VXLAN简明学习笔记(原创)
  10. VMware Workstation 14 Pro 安装 Windows Server 2003(完)
  11. Java面向对象编程 实验报告
  12. 电子商务概论(农)之章节课后题
  13. 如何解决DMS的个人数据隐私问题?ToF技术路线在路上
  14. 标学历年真题2016年版 真考题库1 电子表格
  15. 串口服务器采集需要通讯协议么,C2000-A2-SDX6000-CX1
  16. 跟小静读CLR via C#(06)- 构造器
  17. 微信公共平台配置域名提示,协议头非法
  18. 【台大郭彦甫】Matlab入门教程超详细学习笔记四:数据类型与文件读写(附PPT链接)
  19. Docker | 基于docker安装Redis
  20. js html css淘宝足迹日历效果,JavaScript实现简单日历效果

热门文章

  1. 跑步耳机哪个牌子好,运动耳机品牌排行榜前十名
  2. 为什么说Java不适合做游戏开发,劣势在哪里?
  3. 怎么用ps将cpa报名所用的照片文件修改到20kb以下
  4. 哈夫曼树算法思想设计内线电话号码
  5. zabbix监控交换机
  6. 手机上如何压缩PDF文件大小
  7. Android插拔usb亮屏流程
  8. 并不十分娱乐圈 html5,并不十分娱乐圈养成攻略
  9. linux ubuntu下怎样将pdf格式文件转换为doc格式文件,如何在Ubuntu命令行上将文档转换为PDF格式...
  10. 24岁零基础自学编程,先学哪种语言最好?