计算机网络编程(Linux):I/O多路转接之 select,poll

I/O多路复用(I/O Multiplexing)是一种高效的网络编程技术,允许一个线程同时监控多个文件描述符的状态,当某个文件描述符就绪时进行相应处理。这种技术在高并发服务器中广泛使用。本文将介绍I/O多路复用的核心概念及在Linux中的实现方式。

一、I/O多路复用的基本概念

为什么需要I/O多路复用?

在传统的阻塞I/O模型中,一个线程只能处理一个I/O请求,如果我们想要对来自网络的不同的链接同时进行处理,就需要创建线程,或者进程,这导致我们的程序中存在大量线程,或者进程,浪费系统资源。I/O多路复用通过同时监听多个文件描述符的状态(如可读、可写),在任何一个描述符就绪时通知程序进行操作,从而避免了阻塞等待。

核心思路

I/O多路复用的核心思想是利用内核提供的机制(内核通过判断文件是否做出更改,等操作来改变fd_set,进而返回触发事件的文件描述符),集中管理和监听多个文件描述符,并根据事件就绪情况执行特定操作。这样可以大幅减少线程或进程的数量,提高系统资源使用率,

Select

函数介绍

select函数

int select(int nfds, fd_set *readfds, fd_set *writefds, \fd_set *exceptfds, struct timeval *timeout);

nfds:指定待检测的文件描述符范围,它的值应该是所有文件描述符中最大值加 1。select 会检查文件描述符从 0nfds-1 的状态。未使用的文件描述符范围无需浪费资源。

readfds ,writefds,exceptfds:分别是读,写,异常的文件描述符的位图,我们需要关心哪一个事件,就把对应的文件描述符加入到其位图结构中,传入进函数。

struct timeval {long tv_sec;   // 秒long tv_usec;  // 微秒
};

timeout:select函数的超时事件,select每一次会返回我们设置超时事件的剩余事件,例如,5秒,运行一秒后会返回4秒。同时,我们可以把参数设置为 NULL 阻塞,直到有事件就绪,select才会返回。

select函数返回值 

  • 返回值为正数:表示有文件描述符就绪,返回的数字为就绪的文件描述符数量。
  • 返回值为 0:表示超时,没有任何文件描述符就绪。
  • 返回值为负数:表示调用失败,可通过 errno 获取错误信息

上述所有参数,都需要我们进行一次事件处理后,或者说一次主循环后重新设置,我们需要重新设置关心的文件描述符和事件。

void FD_CLR(int fd, fd_set *set); // 用来清除描述词组set中相关fd 的位
int FD_ISSET(int fd, fd_set *set); // 用来测试描述词组set中相关fd 的位是否为真
void FD_SET(int fd, fd_set *set); // 用来设置描述词组set中相关fd的位
void FD_ZERO(fd_set *set);  // 用来清除描述词组set的全部位

 简单示例

#include <iostream>
#include <memory>
#include <sys/select.h>
#include <stdio.h>
#include <thread>#include <unistd.h>  // 为了使用 sleep 函数模拟输入延时void* example_select(void* args) {fd_set read_fds;FD_ZERO(&read_fds); // 初始化描述符集FD_SET(0, &read_fds); // 添加标准输入(文件描述符 0)struct timeval timeout = {5, 0}; // 超时时间 5 秒// 使用 select 来监视标准输入int ret = select(1, &read_fds, NULL, NULL, &timeout);if (ret > 0 && FD_ISSET(0, &read_fds)) {std::cout << timeout.tv_sec << std::endl;printf("Input is available.\n");} else if (ret == 0) {printf("Timeout occurred.\n");} else {perror("select error");}return NULL;
}void simulate_input() {std::cout << "Simulating input..." << std::endl;std::cin.get();  
}int main() {// 创建两个线程std::thread monitor_thread(example_select, nullptr);  // 监视输入线程std::thread input_thread(simulate_input);  // 模拟输入线程monitor_thread.join();input_thread.join();return 0;
}

 程序使用两个线程,一个线程使用select进行监视,另外一个创建事件就绪,但是对于select的fs_set来说,有设计上的限制,他最大可以同时监视的文件描述符数量为1024,我们可以在select.h头文件里看到

 Poll

对于select来说,Poll的改进就是可以同时监视的文件描述符的限制不是程序,而是硬件的限制,也就是说,对于程序来说没有上限。

函数介绍

fds:这个结构是属于用户维护,也就是说,我们可以使用数据结构对其大小进行动态管理

fd:要监视的文件描述符(例如,套接字、管道等)。events:指定要监听的事件类型,使用 poll 支持的事件标志。revents:返回时,内核填充的已就绪事件类型。使用该字段可以检查哪些事件已经发生。

常见的 eventsrevents 标志:

  • POLLIN:文件描述符可读取。
  • POLLOUT:文件描述符可写入。
  • POLLERR:文件描述符发生错误。
  • POLLHUP:文件描述符发生挂起(例如,连接关闭)。
  • POLLNVAL:文件描述符无效。

 nfds:我们设置的结构体数组的大小。

timeout:poll里的timeout不是结构体,就只是int,单位是毫秒,大于0,就是超时事件,等于0,就是非阻塞,-1就是阻塞。

poll函数的返回值

  • 正数:表示已就绪的文件描述符数量。revents 字段会被填充,表示已发生的事件。
  • 0:表示超时,没有文件描述符就绪。
  • -1:表示错误,errno 会被设置为具体错误代码。

 简单示例

void* example_poll(void* args) {struct pollfd fds[1];  // 使用 pollfd 结构数组来监视文件描述符fds[0].fd = 0;          // 监视标准输入(文件描述符 0)fds[0].events = POLLIN; // 监听可读事件fds[0].revents = 0;     // 初始化 revents,表示返回的事件状态int timeout = 5000;  // 设置超时时间为 5000 毫秒(即 5 秒)// 使用 poll 来监视文件描述符int ret = poll(fds, 1, timeout);if (ret > 0 && (fds[0].revents & POLLIN)) {printf("Input is available.\n");} else if (ret == 0) {printf("Timeout occurred.\n");} else {perror("poll error");}return NULL;
}

只需要把头文件加上,上述示例就可以用。

同时,与select一样,每一次循环,需要我们重新设置这些值,那也就是说,poll与select都需要去循环设置,循环查找就绪的文件描述符,然后循环查找空余位置进行文件描述符的插入(没有任何优化),这就导致我们的效率会很低,就算poll解决的文件描述符上限的问题,循环的问题并没有解决。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/63515.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【原生js案例】webApp实现鼠标移入移出相册放大缩小动画

图片相册这种动画效果也很常见&#xff0c;在我们的网站上。鼠标滑入放大图片&#xff0c;滑出就恢复原来的大小。现在我们使用运动定时器来实现这种滑动效果。 感兴趣的可以关注下我的系列课程【webApp之h5端实战】&#xff0c;里面有大量的css3动画效果制作原生知识分析&…

Spring Boot助力,一键解锁招聘全流程信息精细化管理

2系统相关技术 2.1 Java语言介绍 Java是由SUN公司推出&#xff0c;该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称&#xff0c;也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备了显著的优势和广阔的前景&#…

Day28两个数组的交集

给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 class Solution{public int[] intersection(int[] nums1, int[] nums2) {Set<Integer> set new HashSet<>();for (int i :…

VRRP的知识点总结及实验

1、VRRP VRRP(Virtual Router Redundancy Protocol&#xff0c;虚拟路由器冗余协议)既能够实现网关的备份&#xff0c;又能解决多个网关之间互相冲突的问题&#xff0c;从而提高网络可靠性。 2、VRRP技术概述&#xff1a; 通过把几台路由设备联合组成一台虚拟的“路由设备”…

DP协议:概括

来了来了&#xff01;&#xff01;&#xff01; 开始之前扯点概念&#xff0c;知道DP好在哪里&#xff0c;以及看到它的发展趋势&#xff0c;才知道我们为什么有学习的必要。 DP的优势 DisplayPort&#xff08;DP&#xff09;协议作为一种专为数字音频和视频传输设计的高速串行…

Ant Design Vue 中 Tree 组件复选框修改样式

一、问题 最近需要实现一个业务需求&#xff0c;要修改勾选框中的颜色&#xff0c;默认勾选框的颜色是蓝色&#xff0c;现在需要变成绿色。 1、官网示例&#xff1a; 2、业务需求&#xff1a; 3、具体实现&#xff1a; HTML 部分代码 <template><div class"s…

【JavaWeb后端学习笔记】登录校验(JWT令牌技术、Interceptor拦截器、Filter过滤器)

登录校验 1、JWT令牌技术1.1 JWT令牌介绍1.2 Java代码生成与校验JWT令牌 2、Filter过滤器2.1 Filter过滤器的简单实现2.2 配置拦截路径2.3 Filter接口中的三个方法&#xff1a;2.4 Filter过滤器登录校验2.5 过滤器链 3、Interceptor拦截器3.1 拦截器(Interceptor)的简单实现3.2…

Linux系统下常用资源查看

一、查看CPU使用率 top 命令 top命令可以看到总体的系统运行状态和cpu的使用率 。 %us&#xff1a;表示用户空间程序的cpu使用率&#xff08;没有通过nice调度&#xff09; %sy&#xff1a;表示系统空间的cpu使用率&#xff0c;主要是内核程序。 %ni&#xff1a;表示用户空间且…

Flutter提示错误:无效的源发行版17

错误描述 Flutter从3.10.1 升级到3.19.4&#xff0c;在3.10.1的时候一切运行正常&#xff0c;但是当我将Flutter版本升级到3.19.4后&#xff0c;出现了下方的错误 FAILURE: Build failed with an exception.* What went wrong: Execution failed for task :device_info_plus:…

java+ssm+mysql学生信息管理系统

项目介绍&#xff1a; 使用javassmmysql开发的学生信息管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、教师、学生角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff08;可以新增管理员&#xff09;&#xff1b;专业管理&…

PCB设计规范

过孔设计 过孔盖油工艺&#xff08;也成为连塞带印&#xff09;&#xff1a;常规工艺、免费工艺&#xff0c;无特殊情况也建议使用此工艺。过孔大小建议直径在0.3mm-0.5mm之间。最省钱&#xff0c;效果最好。 非金属化槽孔 PCB制造商在加工非金属化槽孔时通常采用锣刀加工。最…

【C语言】42道大厂笔试题目(选择题)

本篇博客给大家带来的是一些大厂笔试题目&#xff0c;题目难度&#xff1a;简单&#xff0c;适合小白快速入手C语言部分的大厂笔试难度。 &#x1f41f;&#x1f41f;文章专栏&#xff1a;C语言 &#x1f680;&#x1f680;若有问题评论区下讨论&#xff0c;我会及时回答 ❤❤欢…

设置笔记本同时连接内外网

原理&#xff1a;通过笔记本和手机相连&#xff0c;实现双网卡功能能。笔记本连接内网wifi、同时手机端开启usb网络共享&#xff0c;笔记本就有了两个网&#xff0c;然配置那个访问外网&#xff0c;那个访问内网。 1.笔记本wifi连接内网wifi 2.手机端共享网络。 手机打开 -【…

JVM类加载三步解读: 双亲委派模型如何维护Java生态

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持! &#x1f649;Java是面向对象编程&#xff0c;一切皆对象。这些对象是如何从一堆代码变成程序中的一部分&#xff1f;Java虚拟机&#xff08;JVM&#xff09;在这个过程中扮演了至关重要的角色。当你的代码通…

青海摇摇了3天,技术退步明显.......

最近快手上的青海摇招聘活动非常火热&#xff0c;我已经在思考是否备战张诗尧的秋招活动。开个玩笑正片开始&#xff1a; 先说一下自己的情况&#xff0c;大专生&#xff0c;20年通过校招进入杭州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c…

SpringBean生命周期之PostConstruct、PreDestroy详解

在Spring框架中&#xff0c;Bean的生命周期是一个复杂的过程&#xff0c;涉及多个阶段&#xff0c;其中PostConstruct和PreDestroy注解在Bean的初始化和销毁阶段发挥着重要作用。以下是对这两个注解的深入理解&#xff1a; 一、PostConstruct注解 定义与来源 PostConstruct源自…

基于阿里云Ubuntu22.04 64位服务器Java及MySql环境配置命令记录

基于阿里云Ubuntu22.04 64位服务器Java及MySql环境配置命令记录 Java 23 离线环境配置MySql 环境配置MySQL常用命令 Java 23 离线环境配置 下载 Ubuntu环境下 Java 23 离线包 链接: java Downloads. 在Linux环境下创建一个安装目录 mkdir -p /usr/local/java将下载好的jdk压缩…

逆向分析:利用标志位进行爆破破解

信息收集 查程序编写信息 所用工具Detect It Easy Delphi编写&#xff0c;根据此信息选择DeDeDark进行反编译进一步收集可用信息 反编译程序进行信息收集 所用工具DeDeDark 载入要分析的主程序点击[开始处理]进行分析 注&#xff1a;主程序即软件主题程序(长见软件安装完毕…

【工具变量】上市公司企业研发不确定性数据(2013-2023年)

一、测算方式&#xff1a;参考顶刊《中国工业经济》孙薇&#xff08;2023&#xff09;老师的做法&#xff0c;本文从专利的申请与授权的视角出发&#xff0c;以企业当年申请的发明专利中最终未被授权的比例度量研发不确定性 &#xff08;uc&#xff09;。这是因为&#xff0c;相…

centos部署SkyWalking并在springcloud项目中用法举例

文章目录 场景SkyWalking介绍部署部署Storage [单机版Elasticsearch]部署SkyWalking OAP [下载地址](https://skywalking.apache.org/downloads/#SkyWalkingAPM)部署SkyWalking Java AgentspringCloud 使用举例 场景 SkyWalking是应用性能监控平台&#xff0c;可用于分布式系统…