【在Linux世界中追寻伟大的One Piece】多路转接epoll

目录

1 -> I/O多路转接之poll

1.1 -> poll函数接口

1.2 -> poll的优点

1.3 -> poll的缺点

1.4 -> poll示例

1.4.1 -> 使用poll监控标准输入

2 -> I/O多路转接之epoll

2.1 -> 初识epoll

2.2 -> epoll的相关系统调用

2.2.1 -> epoll_create

2.2.2 -> epoll_ctl

2.2.3 -> epoll_wait

2.3 -> epoll工作原理

2.4 -> epoll优点


1 -> I/O多路转接之poll

1.1 -> poll函数接口

#include <poll.h>int poll(struct pollfd* fds, nfds_t nfds, int timeout);// pollfd 结构
struct pollfd 
{int fd; /* file descriptor */short events; /* requested events */short revents; /* returned events */
};

参数说明:

  • fds是一个poll函数监听的结构列表。每一个元素中,包含了三部分内容:文件描述符,监听的事件集合,返回的事件集合。
  • nfds表示fds数组的长度。
  • timeout表示poll函数的超时时间,单位是毫秒(ms)。

events和revents的取值:

事件描述是否可作为输入是否可作为输出
POLLIN数据(包括普通数据和优先数据)可读
POLLRDNORM普通数据可读
POLLRDBAND优先级带数据可读(Linux不支持)
POLLPRI高优先级数据可读,比如TCP带外数据
POLLOUT数据(包括普通数据和优先数据)可写
POLLWRNORM普通数据可写
POLLWRBAND优先级带数据可写

POLLRDHUPTCP连接被对方关闭,或者对方关闭了写操作。它由GNU引入
POLLERR错误

POLLHUP挂起。比如管道的写端被关闭后,读端描述符上将收到POLLHUP事件
POLLNVAL文件描述符没有打开

返回结果:

  • 返回值小于0,表示出错。
  • 返回值等于0,表示poll函数等待超时。
  • 返回值大于0,表示poll由于监听的文件描述符就绪而返回。

1.2 -> poll的优点

不同于select使用三个位图来表示三个fdset的方式,poll使用一个pollfd的指针实现。

  • pollfd结构包含了要监视的event和发生的event,不再使用select"参数-值"传递的方式。接口使用比select更方便。
  • poll并没有最大数量限制(但是数量过大后性能也是会下降)。

1.3 -> poll的缺点

poll中监听的文件描述符数目增多时:

  • 和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符。
  • 每次调用poll都需要把大量的pollfd结构从用户态拷贝到内核中。
  • 同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。

1.4 -> poll示例

1.4.1 -> 使用poll监控标准输入

#include <poll.h>
#include <unistd.h>
#include <stdio.h>int main() 
{struct pollfd poll_fd;poll_fd.fd = 0;poll_fd.events = POLLIN;for (;;) {int ret = poll(&poll_fd, 1, 1000);if (ret < 0) {perror("poll");continue;}if (ret == 0) {printf("poll timeout\n");continue;}if (poll_fd.revents == POLLIN) {char buf[1024] = { 0 };read(0, buf, sizeof(buf) - 1);printf("stdin:%s", buf);}}
}

2 -> I/O多路转接之epoll

2.1 -> 初识epoll

epoll是Linux内核中提供的一种高效的IO多路复用机制,它专为处理大量文件描述符而设计。相比于传统的select和poll机制,epoll在存在大量并发连接且只有少数连接活跃时,能够显著提高系统的CPU利用率。epoll的关键优势在于它在获取就绪事件时,不会遍历所有被监听的文件描述符集,而是只会遍历那些被设备IO事件异步唤醒(通过CPU中断机制)而加入就绪链表的文件描述符集。

按照man手册的说法:是为处理大批量句柄而作了改进的poll。

它是在2.5.44内核中被引进的(epoll(4)is a new API introduced in Linux kernel 2.5.44)它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。

2.2 -> epoll的相关系统调用

2.2.1 -> epoll_create

int epoll_create(int size);

创建一个epoll的句柄。

  • 自从linux2.6.8之后,size参数是被忽略的。
  • 用完之后,必须调用close()关闭。

2.2.2 -> epoll_ctl

int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);

epoll的事件注册函数。

它不同于select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。

  • 第一个参数是epoll_create()的返回值(epoll 的句柄)。
  • 第二个参数表示动作,用三个宏来表示。
  • 第三个参数是需要监听的fd。
  • 第四个参数是告诉内核需要监听什么事。

第二个参数的取值:

  • EPOLL_CTL_ADD:注册新的fd到epfd中。
  • EPOLL_CTL_MOD:修改已经注册的fd的监听事件。
  • EPOLL_CTL_DEL:从epfd中删除一个fd。

struct epoll_event结构如下:

typedef union epoll_data
{void* ptr;int fd;uint32_t u32;uint64_t u64;
} epoll_data_t;struct epoll_event
{uint32_t events; //Epoll eventsepoll_data_t data; //User data variable
}_EPOLL_PACKED;

events可以是以下几个宏的集合:

  • EPOLLIN:表示对应的文件描述符可以读(包括对端SOCKET正常关闭)。
  • EPOLLOUT:表示对应的文件描述符可以写。
  • EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来)。
  • EPOLLERR:表示对应的文件描述符发生错误。
  • EPOLLHUP:表示对应的文件描述符被挂断。
  • EPOLLET:将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
  • EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里。

2.2.3 -> epoll_wait

int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);

收集在epoll监控的事件中已经发送的事件。

  • 参数events是分配好的epoll_event结构体数组。
  • epoll将会把发生的事件赋值到events数组中(events不可以是空指针,内核只负责把数据复制到这个events数组中,不会去帮助我们在用户态中分配内存)。
  • maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size。
  • 参数timeout是超时时间(毫秒,0会立即返回,-1是永久阻塞)。
  • 如果函数调用成功,返回对应I/O上已准备好的文件描述符数目,如返回0表示已超时, 返回小于0表示函数失败。

2.3 -> epoll工作原理

当某一进程调用epoll_create方法时,Linux内核会创建一个eventpoll结构体,这个结构体中有两个成员与epoll的使用方式密切相关。

struct eventpoll 
{/*红黑树的根节点,这颗树中存储着所有添加到 epoll 中的需要监控的事件*/struct rb_root rbr;/*双链表中则存放着将要通过 epoll_wait 返回给用户的满足条件的事件*/struct list_head rdlist;
};
  • 每一个epoll对象都有一个独立的eventpoll结构体,用于存放通过epoll_ctl方法向epoll对象中添加进来的事件。
  • 这些事件都会挂载在红黑树中,如此,重复添加的事件就可以通过红黑树而高效的识别出来(红黑树的插入时间效率是lgn,其中n为树的高度)。
  • 而所有添加到epoll中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当响应的事件发生时会调用这个回调方法。
  • 这个回调方法在内核中叫ep_poll_callback,它会将发生的事件添加到rdlist双链表中。
  • 在epoll中,对于每一个事件,都会建立一个epitem结构体。
struct epitem 
{struct rb_node rbn;//红黑树节点struct list_head rdllink;//双向链表节点struct epoll_filefd ffd; //事件句柄信息struct eventpoll* ep; //指向其所属的 eventpoll 对象struct epoll_event event; //期待发生的事件类型
}
  • 当调用epoll_wait检查是否有事件发生时,只需要检查eventpoll对象中的rdlist双链表中是否有epitem元素即可。
  • 如果rdlist不为空,则把发生的事件复制到用户态,同时将事件数量返回给用户。这个操作的时间复杂度是O(1)。

总结一下,epoll的使用过程就是三部曲:

  • 调用epoll_create创建一个epoll句柄。
  • 调用epoll_ctl,将要监控的文件描述符进行注册。
  • 调用epoll_wait,等待文件描述符就绪。

2.4 -> epoll优点

  • 接口使用方便:虽然拆分成了三个函数,但是反而使用起来更方便高效。不需要每次循环都设置关注的文件描述符,也做到了输入输出参数分离开。
  • 数据拷贝轻量:只在合适的时候调用EPOLL_CTL_ADD将文件描述符结构拷贝到内核中,这个操作并不频繁(而select/poll都是每次循环都要进行拷贝)。
  • 事件回调机制:避免使用遍历,而是使用回调函数的方式,将就绪的文件描述符结构加入到就绪队列中,epoll_wait返回直接访问就绪队列就知道哪些文件描述符就绪。这个操作时间复杂度O(1)。即使文件描述符数目很多,效率也不会受到影响。
  • 没有数量限制:文件描述符数目无上限。

感谢各位大佬支持!!!

互三啦!!!

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

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

相关文章

招聘app开发,人才招聘、求职首要方式

随着互联网的快速发展&#xff0c;各种线上应用成为了大众生活中不可或缺的一部分&#xff0c;不管是购物、娱乐、找工作等都可以通过手机应用进行。因此&#xff0c;对于企业说&#xff0c;线上招聘app至关重要&#xff0c;能够快速帮助企业找到合适的人才。企业直接与求职者交…

学习方法——看差的书籍

CSAPP证明从1中午2点到下午3&#xff1a;40&#xff0c;但是还是只是推理证明而已&#xff0c;但是想起来了课上老师讲的东西了 还可以知道补码运算的大前提知识&#xff01;&#xff01;&#xff01; 但是最好不要一下学这个一下子学哪个&#xff0c;学哪一个都不能尽情投入。…

【人工智能】Transformers之Pipeline(二十三):文档视觉问答(document-question-answering)

​​​​​​​ 目录 一、引言 二、文档问答&#xff08;document-question-answering&#xff09; 2.1 概述 2.2 impira/layoutlm-document-qa 2.2.1 LayoutLM v1 2.2.2 LayoutLM v2 2.2.3 LayoutXLM 2.2.4 LayoutLM v3 2.3 pipeline参数 2.3.1 pipeline对象实例化…

Python酷库之旅-第三方库Pandas(206)

目录 一、用法精讲 961、pandas.IntervalIndex.mid属性 961-1、语法 961-2、参数 961-3、功能 961-4、返回值 961-5、说明 961-6、用法 961-6-1、数据准备 961-6-2、代码示例 961-6-3、结果输出 962、pandas.IntervalIndex.length属性 962-1、语法 962-2、参数 …

【论文阅读】利用SEM二维图像表征黏土矿物三维结构

导言 在油气储层研究中&#xff0c;黏土矿物对流体流动的影响需要在微观尺度上理解&#xff0c;但传统的二维SEM图像难以完整地表征三维孔隙结构。常规的三维成像技术如FIB-SEM&#xff08;聚焦离子束扫描电子显微镜&#xff09;虽然可以获取高精度的3D图像&#xff0c;但成本…

前端入门一之ES6--面向对象、够着函数和原型、继承、ES5新增方法、函数进阶、严格模式、高阶函数、闭包

前言 JS是前端三件套之一&#xff0c;也是核心&#xff0c;本人将会更新JS基础、JS对象、DOM、BOM、ES6等知识点&#xff0c;这篇是ES6;这篇文章是本人大一学习前端的笔记&#xff1b;欢迎点赞 收藏 关注&#xff0c;本人将会持续更新。 文章目录 JS高级 ES61、面向对象1.1…

数据安全、信息安全、网络安全区别与联系

关键字&#xff1a; 信息安全 数据安全 网络安全 [导读] 在 “互联网 ” 被广泛提及的今天&#xff0c;安全问题也越来越多的受到人们关注&#xff0c;然而很多人对于 “信息安全”、“数据安全”、“网络安全” 的概念并不是很清楚。我们汇总了官方机构给这三者的定义&#…

Linux——简单认识vim、gcc以及make/Makefile

前言&#xff1a;大佬写博客给别人看&#xff0c;菜鸟写博客给自己看&#xff0c;我是菜鸟。 1、vim操作&#xff1a; 默认打开vim时&#xff0c;vim处于命令模式。(在其他模式中&#xff0c;Esc就能够返回命令模式) 常用的命令有&#xff1a; n gg&#xff1a;跳转到n行&…

Java反序列化之CommonsCollections2链的学习

一、前言 Apache Commons Collections 是一个著名的辅助开发库&#xff0c;包含了一些Java中没有的数据结构和辅助方法&#xff0c;不过随着Java 9 以后的版本中原生库功能的丰富&#xff0c;以及反序列化漏洞的影响&#xff0c;它也在逐渐被升级或替代。 在2015年底的common…

前端web

题目&#xff1a;制作带有下拉悬停菜单的导航栏 效果图 一、先制作标签 <body> <div id"menu"> <div id"container"> <div class"item">游戏1 <div class…

【大数据学习 | kafka高级部分】kafka中的选举机制

controller的选举 首先第一个选举就是借助于zookeeper的controller的选举 第一个就是controller的选举&#xff0c;这个选举是借助于zookeeper的独享锁实现的&#xff0c;先启动的broker会在zookeeper的/contoller节点上面增加一个broker信息&#xff0c;谁创建成功了谁就是主…

Android 开发指南:初学者入门

Android 是全球最受欢迎的移动操作系统之一&#xff0c;为开发者提供了丰富的工具和资源来创建各种类型的应用程序。本文将为你提供一个全面的入门指南&#xff0c;帮助你从零开始学习 Android 开发。 目录 1. 了解 Android 平台[1]2. 设置开发环境[2]3. 学习基础知识[3]4. 创…

漏洞挖掘 | 某医院小程序支付漏洞+越权

漏洞挖掘 | 某医院小程序支付漏洞越权 登陆后点击个人信息&#xff0c;抓包&#xff0c;放到repeter模块 修改strUserID参数可以越权查看别人信息 放intruder模块可以跑数据&#xff0c;这里有几万信息泄露 回到首页&#xff0c;点击医生咨询功能点 随便选一个需要付费的医…

MFC图形函数学习07——画扇形函数

绘制扇形函数是MFC中绘图的基本函数&#xff0c;它绘制的仍是由椭圆弧与椭圆中心连线构成的椭圆扇形&#xff0c;特例是由圆弧与圆心连线构成的圆扇形。 一、绘制扇形函数 原型&#xff1a;BOOL Pie(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4); …

基于Python的膳食健康系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

头歌网络安全(11.12)

头歌禁止复制解决 必须先下篡改猴&#xff01;&#xff01;&#xff01;&#xff01; 头歌复制助手 Educoder Copy Helperhttps://scriptcat.org/zh-CN/script-show-page/1860 Java生成验证码 第1关&#xff1a;使用Servlet生成验证码 任务描述 本关任务&#xff1a;使用se…

ROM修改进阶教程------安卓14 安卓15去除app签名验证的几种操作步骤 详细图文解析

在安卓14 安卓15的固件中。如果修改了系统级别的app。那么就会触发安卓14 15的应用签名验证。要么会导致修改的固件会进不去系统,或者进入系统有bug。博文将从几方面来解析去除安卓14 15应用签名验证的几种方法。 💝💝💝通过博文了解: 1💝💝💝-----安卓14去除…

第七部分:2. STM32之ADC实验--AD多通道(AD采集三路传感器模块实验:光敏传感器、热敏传感器、反射式传感器附赠温湿度传感器教程)

这个多通道采用非扫描模式--单次转换模式 1.代码配置链路图 2. ADC的输入通道 3.ADC的非扫描模式的转换模式&#xff08;单次和连续&#xff09; 4.ADC的扫描模式的转换模式&#xff08;单次和连续&#xff09; 5.采集校准 代码实验&#xff1a; 代码部分&#xff1a; #inclu…

crond 任务调度 (Linux相关指令:crontab)

相关视频链接 crontab 进行 定时任务 的设置 概述 任务调度&#xff1a;是指系统在某个时间执行的特定的命令或程序 任务调度的分类&#xff1a; 1.系统工作&#xff1a;有些重要的工作必须周而复始地执行。如病毒扫描等。 2.个别用户可能希望执行某些程序&#xff0c;比如…

基于python 的opencv 使用GrabCut算法分割图像代码

#利用grabcut算法分割图像import numpy as np import cv2 from matplotlib import pyplot as plt import warningswarnings.filterwarnings("ignore", module "matplotlib")imgpath E:/code/image_opencv_test/lena.jpg img cv2.imread(imgpath)Coords1x…