当前位置: 首页 > news >正文

【Linux】从零开始使用多路转接IO --- poll

在这里插入图片描述

碌碌无为,则余生太长;
欲有所为,则人生苦短。
--- 中岛敦 《山月记》---

从零开始使用多路转接IO

  • 1 前言
  • 1 poll接口介绍
  • 3 代码编写
  • 4 总结

1 前言

上一篇文章我们学习了多路转接中的Select,其操作很简单,但有一些缺陷:

  1. 每次调用 select,都需要手动设置 fd 集合, 从接口使用角度来说也非常不便。
  2. 每次调用 select, 都需要把 fd 集合从用户态拷贝到内核态, 这个开销在 fd 很多时会很大。这个是多路转接IO无法避免的问题!
  3. 同时每次调用 select 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 很多时很大。
  4. select 支持的文件描述符数量太小!虽然操作系统中文件描述符也有限制,但是这是操作系统的缺陷。同样select也是缺点

而poll方案可以解决其中的两个缺点:

  • select支持的文件描述符少,poll理论上可以支持无限个文件描述符。
  • select每次调用接口都需要手动设置fd集合,poll不需要!

那么接下来我们就来看poll是怎样实现的。

1 poll接口介绍

首先poll的作用与select一模一样:等待多个文件描述符!只负责等待!

我们来看看poll接口:

OLL(2)                                                                   Linux Programmer's Manual                                                                   POLL(2)NAMEpoll, ppoll - wait for some event on a file descriptorSYNOPSIS#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);#define _GNU_SOURCE         /* See feature_test_macros(7) */#include <signal.h>#include <poll.h>int ppoll(struct pollfd *fds, nfds_t nfds,const struct timespec *tmo_p, const sigset_t *sigmask);

poll接口中只有三个参数:

  1. struct pollfd *fds:这时一个文件描述符数组,其中每个元素是一个结构体,其中包含文件描述符,需要处理的事件类型。
  2. nfds_t nfds:表示文件描述符的数量!
  3. timeout:输入性参数,这里直接采用的是毫秒,不使用结构体!等于0时是非阻塞IO,等于-1时是阻塞IO!
  4. 返回值表示是否成功:大于0 即有n个就绪了;等于0表示超时了;小于0就是poll出错了!

我们来看看struct pollfd内部是怎么样的 :

struct pollfd {int   fd;         /* file descriptor */short events;     /* requested events */short revents;    /* returned events */};

我们对比一下select,select需要传入三个事件集,输入输出性参数,每次都会发生改变!所以才需要每次调用都要进行初始化。而poll使用一个结构体,对于这个文件描述符有两种事件:requested events 与 returned events!输入输出并不互相干扰!那么就解决了select需要不断初始化的问题。

那么事件类型有哪些呢?

宏定义描述
POLLIN普通或优先级带数据可读
POLLRDNORM同POLLIN
POLLRDBAND数据可读(优先级带数据)
POLLPRI高优先级数据可读
POLLOUT普通数据可写
POLLWRNORM同POLLOUT
POLLWRBAND数据可写(优先级带数据)
POLLERR发生错误
POLLHUP挂起,对方关闭连接
POLLNVAL描述字不是一个打开的文件

这些都是宏定义,short events;是一个16位位图,可以通过宏定义进行匹配设置!我们想要查看哪些事件,或者有哪些事件就绪了,就都可以通过位运算进行判断就可以了!

通过结构体的两个位图:

  1. 用户就可以告诉内核需要帮我们对fd的哪些事件进行等待了
  2. 内核也可以通过位图告诉用户fd的哪些事件就绪了!

3 代码编写

我们仅仅需要对select的代码做出一些修改即可:

首先,poll需要一个struct pollfd数组,这里储存需要处理的fd。初始化事遍历进行将对应fd设置为-1,事件设置为0,将listen套接字加入就可以:

	void Initserver(){// 对数组进行初始化for (int i = 0; i < gnum; i++){fd_array[i].fd = gdefault;fd_array[i].events = 0;fd_array[i].revents = 0;}// 加入监听套接字fd_array[0].fd = _listensock->GetSockfd();fd_array[0].events = POLLIN;}//...// pollstruct pollfd fd_array[gnum];

然后对Loop函数进行修改,我们不在需要对数据遍历更新rfds了,这样代码看起来就整洁了许多!

void Loop(){// 进入服务while (true){// 创建timeoutint timeout = 1000;// 进行selectint n = ::poll(fd_array, gnum, timeout);switch (n){case 0:// 超时LOG(DEBUG, "timeout \n");break;case -1:// 出错了LOG(ERROR, "select error\n");break;default:// 正常LOG(INFO, "have event ready: n = %d\n", n);// 处理事件HandlerEvent();PrintDebug();break;}}}

接下来就是HandlerEvent函数,进行判断的策略依然是遍历,这里只关心读事件:

void HandlerEvent(){// 遍历fd_array判断是否有就绪的新事件for (int i = 0; i < gnum; i++){if (fd_array[i].fd == gdefault)continue;// 如果有新事件if (fd_array[i].revents & POLLIN){// 进行判断是scokfd 还是普通fdif (fd_array[i].fd == _listensock->GetSockfd()){Accepter();}// 普通fd 进行正常读写else{HandlerIO(fd_array[i]);}}}}

然后就是对于普通套接字和监听套接字的处理,针对数组进行稍微修改即可:

void Accepter(){// 连接事件就绪InetAddr addr;int sockfd = _listensock->Accepter(&addr); // 已经就绪 ,不会阻塞// 这时会得到一个新连接if (sockfd > 0){LOG(DEBUG, "get a new link , client info %s:%d\n", addr.Ip().c_str(), addr.Port());// 将新获取的fd加入到数组中LOG(INFO, "get new fd :%d\n", sockfd);bool flag = false;for (int i = 0; i < gnum; i++){if (fd_array[i].fd == gdefault){flag = true;fd_array[i].fd = sockfd;fd_array[i].events = POLLIN;break;}elsecontinue;}if (flag == false){LOG(WARNING, "fd_array have fill!\n");return;// 可以进行扩容}}}void HandlerIO(struct pollfd &sp){char buffer[1024];int n = ::recv(sp.fd, buffer, sizeof(buffer) - 1, 0);if (n > 0){// 读取到了数据buffer[n] = 0;std::string echo_str = "[client say]#";echo_str += buffer;std::cout << echo_str << std::endl;// 返回一个报文std::string content = "<html><body><h1>hello bite</h1></body></html>";std::string ret_str = "HTTP/1.0 200 OK\r\n";ret_str += "Content-Type: text/html\r\n";ret_str += "Content-Length: " + std::to_string(content.size()) + "\r\n\r\n";ret_str += content;// echo_str += buffer;::send(sp.fd, ret_str.c_str(), ret_str.size(), 0); // 临时方案}else if (n == 0){// 此时fd退出了LOG(INFO, "fd:%d quit!\n", sp.fd);::close(sp.fd);sp.fd = gdefault;sp.events = 0;sp.revents = 0;}else{LOG(ERROR, "recv error! errno:%d\n", errno);::close(sp.fd);sp.fd = gdefault;}}

来看效果:
在这里插入图片描述
很好的实现了我们的需求!代码也比select更加的简单了!

4 总结

Poll的底层其实也是遍历,对我们传入的数据进行遍历,这样的效率其实比select并不能高出太多!也就是说poll依然有这样的缺点:

  1. 每次调用 select, 都需要把 fd 集合从用户态拷贝到内核态, 这个开销在 fd 很多时会很大。这个是多路转接IO无法避免的问题!
  2. 同时每次调用 select 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 很多时很大。

这样poll 的处境就很尴尬,没有select资历早,适配性不如select。性能又比不过epoll!
下一篇文章我们来学习epoll!

相关文章:

【Linux】从零开始使用多路转接IO --- poll

碌碌无为&#xff0c;则余生太长&#xff1b; 欲有所为&#xff0c;则人生苦短。 --- 中岛敦 《山月记》--- 从零开始使用多路转接IO 1 前言1 poll接口介绍3 代码编写4 总结 1 前言 上一篇文章我们学习了多路转接中的Select&#xff0c;其操作很简单&#xff0c;但有一些缺…...

Docker配置宿主机目录和网络映射

容器挂载宿主机目录 在Docker中&#xff0c;你可以通过-v或--volume选项将宿主机的目录挂载到容器中。这可以让你在容器和宿主机之间共享文件。 例如&#xff0c;如果你想将宿主机的/home/user/data目录挂载到容器的/data目录&#xff0c;你可以使用以下命令&#xff1a; do…...

第十七课 component组件解析

component组件解析 component组件的写法在众多组件写法中算是比较简单的&#xff0c;component组件结构组成如下&#xff1a; 1&#xff09;组件名 2&#xff09;组件模板 3&#xff09;利用Vue对象进行生成 基础示例&#xff1a; <div id"app"><test>…...

求余和求模是不是一样的,就要看看计算机中的 fix 和 floor 区别

在计算机中&#xff0c;fix和floor是两个不同的取整函数&#xff0c;它们各自有不同的取整规则。以下是fix和floor的详细区别&#xff1a; 一、定义与功能 fix函数 定义&#xff1a;fix函数是朝零方向取整的函数&#xff0c;即它会返回小于或等于&#xff08;对于正数&#xf…...

00 递推和递归的核心讲解

递归的步骤 说 f(n)含义返回/xx f(n)等价式子在第二步中观察趋势&#xff0c;发现边界值&#xff08;分类递归&#xff09;和终止值&#xff08;return&#xff09; 递归优化思路 记忆化 递推/动态规划的步骤 说f(n)含义循环 关系式列 初值 综上&#xff0c;题目分为两类&a…...

深度学习常用开源数据集介绍【持续更新】

DIV2K 介绍&#xff1a;DIV2K是一个专为 图像超分辨率&#xff08;SR&#xff09; 任务设计的高质量数据集&#xff0c;广泛应用于计算机视觉领域的研究和开发。它包含800张高分辨率&#xff08;HR&#xff09;训练图像和100张高分辨率验证图像&#xff0c;每张图像都具有极高…...

rust编写的系统监测器

系统监测器 技术栈 rusttaurivue3vue-echartsrsbuild 软件介绍 用于查看电脑的硬件信息&#xff0c;实时监测cpu&#xff0c;内存&#xff0c;硬盘&#xff0c;网络&#xff0c;进程等系统资源 图形化&#xff0c;动态化展示&#xff0c;美观实用 软件截图 下载 https:/…...

【MyBatis源码】CacheKey缓存键的原理分析

文章目录 Mybatis缓存设计缓存KEY的设计CacheKey类主体CacheKey组成CacheKey如何保证缓存key的唯一性 Mybatis缓存设计 MyBatis 每秒过滤众多数据库查询操作&#xff0c;这对 MyBatis 缓存键的设计提出了很高的要求。MyBatis缓存键要满足以下几点。 无碰撞&#xff1a;必须保证…...

034_Structural_Transient_In_Matlab结构动力学问题求解

结构动态问题 问题描述 我们试着给前面已经做过的问题上加一点有趣的东西。 结构静力学求解 当时求解这个问题&#xff0c;在最外面的竖直切面加载了一个静态的固定的力。下面我们试试看在上方的表面增加一个脉冲压力载荷。 采用统一的有限元框架&#xff0c;定义问题&…...

项目模块十五:HttpResponse模块

一、模块设计思路 存储HTTP应答要素&#xff0c;提供简单接口 二、成员变量 int _status; // 应答状态码 unordered_map<string, string> _headers; // 报头字段 string _body; // 应答正文 bool _redirect_flag; // 是否重定向信息 stri…...

推荐一款优秀的pdf编辑器:Ashampoo PDF Pro

Ashampoo PDF Pro是管理和编辑 PDF 文档的完整解决方案。程序拥有您创建、转换、编辑和保护文档所需的一切功能。根据需要可以创建特定大小的文档&#xff0c;跨设备可读&#xff0c;还可以保护文件。现在您还能像编辑Word文档一样编辑PDF! 软件特点 轻松处理文字 如 Microso…...

【系统架构设计师】2024年上半年真题论文: 论模型驱动架构设计方法及其应用(包括解题思路和素材)

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2024年上半年 试题3)解题思路1、模型驱动架构能够为软件开发带来的好处2、模型驱动架构的开发过程论文素材参考真题题目(2024年上半年 试题3) 模型驱动架构设计是一种用于应用系统开发的软件设计方法…...

国内短剧源码短剧系统搭建小程序部署H5、APP打造短剧平台

​在当今的互联网时代&#xff0c;短剧作为一种新兴的娱乐形式&#xff0c;受到了越来越多用户的喜爱。为了提供更好的用户体验和满足用户需求&#xff0c;一个好的短剧系统需要具备多元化的功能和优质的界面设计。 本文将介绍国内短剧源码短剧系统搭建小程序部署H5、APP所需的…...

Java集合框架面试指南

Java集合框架面试指南 文章目录 Java集合框架面试指南ArrayList特点&#xff1a;LinkedList特点&#xff1a;ArrayDeque特点&#xff1a;PriorityQueue特点&#xff1a;HashMap特点&#xff1a;HashSet特点&#xff1a;LinkedHashMap特点LinkedHashMap经典用法 TreeMap特点Conc…...

八、MapReduce 大规模数据处理深度剖析与实战指南

MapReduce 大规模数据处理深度剖析与实战指南 一、绪论 在当今的大数据时代背景下&#xff0c;海量数据的处理已然成为企业及科研机构所面临的重大挑战。MapReduce 作为一种高效的分布式计算模型&#xff0c;在大规模数据处理领域中发挥着至关重要的作用。本文将深入阐释 MapR…...

开源免费的API网关介绍与选型

api网关的主要作用 API网关在现代微服务架构中扮演着至关重要的角色&#xff0c;它作为内外部系统通信的桥梁&#xff0c;不仅简化了服务调用过程&#xff0c;还增强了系统的安全性与可管理性。例如&#xff0c;当企业希望将内部的服务开放给外部合作伙伴使用时&#xff0c;直…...

OpenCV视觉分析之目标跟踪(5)目标跟踪类TrackerMIL的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 MIL 算法以在线方式训练分类器&#xff0c;以将目标从背景中分离出来。多重实例学习&#xff08;Multiple Instance Learning&#xff09;通过在…...

二级列表联动

介绍 本示例主要介绍了List组件实现二级联动&#xff08;Cascading List&#xff09;的场景。 该场景多用于商品种类的选择、照片不同类型选择等场景。 效果图 使用说明&#xff1a; 滑动二级列表侧控件&#xff08;点击没用&#xff09;&#xff0c;一级列表随之滚动。&…...

「C/C++」C++ 标准库 之 #include<sstream> 字符串流库

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...

深入理解跨域资源共享(CORS)安全问题原理及解决思路

目录 引言 CORS 基础 CORS 安全问题原理 解决思路 结论 引言 跨域资源共享&#xff08;CORS, Cross-Origin Resource Sharing&#xff09;是现代Web应用中不可或缺的一部分&#xff0c;特别是在前后端分离的架构中。CORS允许一个域上的Web应用请求另一个域上的资源&#…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...