| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> I/O复用 :select poll epoll -> 正文阅读 |
|
[系统运维]I/O复用 :select poll epoll |
I/O复用就是不用产生多个线程的情况下,处理多个客户端发来的数据I/O复用使得程序能同时监听多个文件描述符,提高程序性能使用情况:1.同时需要处理多个套接字?? 2.同时处理用户输入和网络连接? 3.同时处理监听套接字和连接套接字(用的最多)? 4.同时处理TCP、UDP请求? 5.同时监听多个端口,处理多种服务?? 等等 读事件:对描述符读的时候不会阻塞,会得到数据,只要不阻塞,读事件就绪的,接收缓冲区如果有数据可以读,读事件就绪的,发送缓冲区有空间,那么写事件就绪的sockfd:客户端connect连接服务器,有读事件产生 连接套接字:接收缓冲区中有数据有读事件,客户端关闭套接字有读事件 文件描述符就绪条件可读:1.socke套接字内核接收缓存区中字节数大于或等于低水位标记SO_PCVLOWAT(一般为1,也就是有数据就会有读事件),可以无阻塞读操作,且读操作返回字节数大于0 2.socket套接字同系的对方关闭连接时,此时socket套接字有读操作返回0 3.监听套接字上有新的来自客户端的连接时会有读操作 4.socket上有未处理的错误,此时使用getsockopt来读取清除该错误 可写:1.socket上有未处理的错误,此时使用getsockopt来读取清除该错误 2.socket内核发送缓存区中可用字节数大于或等于低水位标记SO_SNDLOWAT,此时可以无阻塞写操作,写操作返回值大于0 3.socket的写操作被关闭,对写操作被关闭的socket执行写操作将触发SIGPIPE信号 4.socket使用非阻塞connect()连接成功或失败后会返回错误信息 select将所有文件描述符存入一个集合,在将集合调入select()中,返回值为几就有几个数据就绪,-1返回失败,返回0超时,再将所有描述符遍历一遍,找到就绪描述符,处理数据 头文件 #include<sys/select.h> select(最大描述符加1,读集合,写集合,异常集合,超时时间结构体空就一直阻塞) fd_set这个集合中,一个位表示一个文件描述符,一共1024个 FD_ZERO ( ) 清空整个集合 FD_SET ( ) 将集合中就描述符就绪对应的位置置为1 FD_ISSET ( )检测有没有被设置,按位与,看是否为真,为真说明就绪 poll:系统调用和select类似,都是在指定时间内比轮询一定数量的描述符,测试其中是否有就绪的描述符头文件 #include<poll.h> 创建结构体数组 struct pollfd fds[ ]; 结构体数组初始化 ?结构体数组中 revents成员是用来判断套接字里面的事件是否为读或者写等一些事件的 poll(结构体数组,数组元素个数,超时时间) epoll :linux上一个特有的I/O服用函数,实现上和select、poll差异很大,它是由一组函数来完成任务,它把用户关心的文件描述符上的事件放在内核的事件表里,无须每次调用都重复传入描述符集合或事件集合,但它需要使用额外的文件描述符来唯一标识内核中的事件表头文件 #include<sys/epoll> 第一步 epoll_create( 告诉内核事件表的大小) //创建一个文件描述符来标识在内核中的事件表 返回的epfd是一个id ,通过epfd可以指定要访问的内核事件表里的事件 第二步 epoll_clt(? ) //操作内核事件表? 动态维护 EPOLL_CTL_ADD? //往内核事件表里面添加元素的 EPOLL_CTL_MOD? //修改内核事件表上的事件 EPOLL_CTL_DEL? //删除内核事件表的事件 第三步 epoll_wait () //等着内核事件表中就虚的描述符,返回就绪描述符的个数 epoll LT和ET模式LT(边缘触发) : 当客户端向接收缓冲区发数据,接收缓冲区中有数据,读事件就绪,recv读走一个后,I\O函数提醒还有数据,认为读事件依然就绪,会继续读,这种情况不会丢数据 ET(水平触发): 客户端发来数据接收缓冲区中有数据,读事件就绪,recv读走一个后没读完,哪怕缓冲区还有数据,I\O函数不会提醒,第二波数据发来时候,服务器才会第二次检测到读事件发生,这时候又读走一个,但是还没读完,所以说就是在客户端发数据的时候才有读事件就绪,服务器不管读了几个,只会读一次,并不会有读事件产生,只有客户端再次发送数据时才会有读事件产生,这就要求了 要一次性把数据读完,讲求高效率 epoll?? ET模式??1.首先添加事件表里设置ET模式 2.设置循环读取的能力,无论一次发多少,全部接收完当我们设置ET模式时候,recv在接收数据时候出错会有特殊的错误码,具体问题具体分析? 1.recv真的就是接收错误 2.recv在接收时候接收缓冲区里没有数据了,错误码为EAGAIN、EWOULDBLOCK 你要去添加错误码判断,是否为上面两个,使用的头文件#include<errno.h> 3.头文件#include<fcntl.h>? //将描述符设置为非阻塞fcntl(描述符、非阻塞命令、...)? //??? O_NONBLOCK? 非阻塞标志? 失败返回-1 ET与LT模式区别LT:?? 事件就绪,接收缓冲区如果还有数据,I/O函数会一直提醒我们,知道处理完数据 ET:? 事件就绪I/O函数只提醒一次,当下次客户端再发消息时,才再次接收 select、poll、epoll之间区别1.select? poll? 什么平台都可以用 ?? epoll? 只能在linux平台上用 2.select 能处理1024个描述符? 三种事件 读、写、异常三类事件类型 ?? poll? 可以处理的描述符比select更多???? 事件类型有读、写、挂断、异常等等?? (On) ?? epoll? 也可以处理的描述符>1024,对于大量的文件描述符来说,epoll的时间复杂度(O1)小于poll 3.select、poll是实现的轮询的方式,需要遍历 (On) ?? epoll? 给每一个描述符注册回调函数的方式,谁就绪了谁返回,效率高??? (O1) 4.select、poll每次循环都要将所有描述符拷贝到内核空间 ?? epoll在内核中创建事件表,每个描述符只加一次 5.select、poll遍历所有的描述符找到就绪描述符O(n) ?? epoll? wait返回就是有几个就绪描述符,也就遍历几个,无需反复 传入用户感兴趣的 事件 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 12:06:10- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |