一、epoll概述

epoll的本质是一个【红黑树】。监听结点为根节点。

大量并发,少量活跃效率高。

epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。

目前epelllinux大规模并发网络程序中的热门首选模型。

1、epoll特点

  • 没有文件描述符1024的限制;
  • 将需要监听的文件描述符上树之后,以后每次监听都不要再次将需要监听的文件描述符拷贝到内核;
  • 返回的是已经变化的文件描述符,不需要遍历红黑树;

2、epoll工作原理

红黑树:树上每个节点都是一个epoll_event结构体

epoll除了提供select/poll那种IO事件的电平触发(Level Triggered)外,还提供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

可以使用cat命令查看一个进程可以打开的socket描述符上限。

cat /proc/sys/fs/file-max

如有需要,可以通过修改配置文件的方式修改该上限值。

sudo vi /etc/security/limits.conf
在文件尾部写入以下配置,soft软限制,hard硬限制。如下图所示。
* soft nofile 65536
* hard nofile 100000

二、epoll的基础API(3个)

1、创建红黑树【epoll_create()】

创建一个epoll句柄,参数size用来告诉内核监听的文件描述符的个数,跟内存大小有关。

#include <sys/epoll.h>int epoll_create(int size)

参数:

  • size:监听的文件描述符的上限数量(内核参考值),2.6版本之后填1即可; Since Linux 2.6.8, the size argument is ignored, but must be greater than zero;
  • 返回值(树的句柄):
    • 成功:非负文件描述符;returns  a file descriptor referring to the new epoll instance.  This file descriptor is used for all the subsequent calls to the epoll interface.  When no longer required, the file descriptor returned by epoll_create() should be closed by  using  close(2).   When  all  file descriptors referring to an epoll instance have been closed, the kernel destroys the instance and releases the associated resources for reuse.
    • 失败:-1,设置相应的errno

2、将需要监听的“文件描述符”上树、下树、修改【epoll_ctl()】

控制某个epoll监控的文件描述符上的事件:注册、修改、删除。

#include <sys/epoll.h>int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

参数:

  • epfd:为epoll_creat创建的红黑树树的句柄
  • op:表示动作,用3个宏来表示:
    • EPOLL_CTL_ADD (注册新的fdepfd):上树
    • EPOLL_CTL_MOD (修改已经注册的fd的监听事件):修改
    • EPOLL_CTL_DEL (从epfd删除一个fd):下树
  • fd:待处理(上树、下树、修改)的“文件描述符”;上树之后对应event;
  • 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 events */epoll_data_t data;        需要监听的文件描述符 /* User data variable */
};

结构体 epoll_event中的events选项:

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

2.1 将文件描述符上树

创建红黑树

int myepfd = epoll_create(1);

将文件描述符cfd上树

struct epoll_event ev;
ev.data.fd = cfd;
ev.events = EPOLLIN; // 待监听的事件为“read”事件// 上树
// 待操作的树为myepfd
// 上树的文件描述符为cfd,对应的树上的节点为 &ev
epoll_ctl(myepfd, EPOLL_CTL_ADD, cfd, &ev);

3、监听【epoll_wait()】

#include <sys/epoll.h>int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

参数:

  • epfd:树的句柄;
  • events:用来存内核得到事件的集合,可简单看作数组(接收树上变化的节点的数组的首地址)。
  • maxevents:    数组events的大小,这个maxevents的值不能大于创建epoll_create()时的size,
  • timeout:    是超时时间
    • -1:    阻塞(永久监听)
    • 0:    立即返回,非阻塞
    • >0:    指定毫秒
  • 返回值:    成功返回变化的文件描述符的数量,出错返回-1

三、epoll案例

1、epoll监听无名管道pipe

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/epoll.h>
int main(int argc, char *argv[])
{//创建数组,用于保存管道的2个文件描述符(一个读端,一个写端)int fd[2]; //创建无名管道pipe(fd);//创建子进程pid_t pid;pid = fork();if(pid < 0)perror("");else if(pid == 0)  // 子进程{close(fd[0]); // 关闭pipe的读端,只给父进程写数据发过去char buf[5];char ch='a';while(1){sleep(3);memset(buf,ch++,sizeof(buf)); // 第一次写a,第二次写b...write(fd[1], buf, 5);}}else    // 父进程{close(fd[1]); // 关闭pipe的写端,只读取从子进程过来的数据//创建树int epfd = epoll_create(1);struct epoll_event ev,evs[1];ev.data.fd = fd[0];ev.events = EPOLLIN;//上树epoll_ctl(epfd,EPOLL_CTL_ADD,fd[0],&ev);//监听while(1){int n = epoll_wait(epfd,evs,1,-1);if(n == 1){char buf[128]="";int ret  = read(fd[0],buf,sizeof(buf));if(ret <= 0){close(fd[0]);epoll_ctl(epfd,EPOLL_CTL_DEL,fd[0],&ev);break;}else{printf("%s\n",buf);}}}}return 0;
}

Linux网络编程多路IO复用----epoll_城南花已开.jpg的博客-CSDN博客

Linux网络编程(六)-高并发服务器03-I/O多路复用03:epoll【红黑树;根节点为监听节点】【无宏FD_SETSIZE限制;不需每次都将要监听的文件描述符从应用层拷贝到内核;不需遍历树】相关推荐

  1. linux网路编程之多线程并发服务器

    1)在使用进程模型开发服务器过程中考虑以下问题 (1)调整进程内最大文件描述符上限 (2)线程如有共享,考虑线程同步 (3)客户端线程退出时,做退出处理(线程分离,自动回收) (4)系统负载,随着链接 ...

  2. linux网路编程之多进程并发服务器

    1)使用多进程并发服务器考虑的因素: (1)父进程描述最大文件描述符的个数(父进程需要关闭accept返回的新文件描述符) (2)系统内可创建进程的个数(与内存大小相关) (3)进程创建过多是否降低整 ...

  3. libevent c++高并发网络编程_高并发编程学习(2)——线程通信详解

    前序文章 高并发编程学习(1)--并发基础 - https://www.wmyskxz.com/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-j ...

  4. Linux IO多路复用之epoll网络编程,高并发的使用例子 (含源码)

    本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一行,然 ...

  5. python网络编程及高并发问题

    面试其他篇 目录: 1.1 转载于:https://www.cnblogs.com/xiaonq/p/10460298.html

  6. Proxy源代码分析--谈谈如何学习linux网络编程

    Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到,Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该是 ...

  7. Linux高并发服务器开发---笔记4(网络编程)

    0705 第4章 项目制作与技能提升 4.0 视频课链接 4.1 项目介绍与环境搭建 4.2 Linux系统编程1.4.3 Linux系统编程2 4.4 多进程 1-9 10.进程间通信☆☆☆ 4.5 ...

  8. Linux 高并发服务器实战 - 1 Linux系统编程入门

    Linux 高并发服务器实战-1Linux系统编程入门 在本机和服务器端设置公共密钥(配置免密登录) 在本机cmd里输入 ssh-keygen -t rsa,生成本机的公密钥 在服务器端里也配置 ss ...

  9. [Linux网络编程]高并发-Select模型

    概要介绍 一般情况下,处理socket通信一个线程或者进程在处理读写的时候要么阻塞在那一直等要么非阻塞然后过会查看是否可读可写,这样会浪费大量的资源,假如需要对多个套接字进行处理读写那么得开很多个线程 ...

最新文章

  1. mysql 性能优化索引、缓存、分表、分布式实现方式。
  2. 算法优化:rgb向yuv的转化最优算法,快得让你吃惊!
  3. android 编译器有问题,Android Studio 3.0 Beta 2发布:解决编译器bug
  4. 19春学期《计算机应用基础》123,福师11春学期《计算机应用基础》在线作业一...
  5. 从两个应用突然流行来看,机会永远存在
  6. RGB和CMYK的区别
  7. 华硕路由器ddns设置_华硕RT-AC86U路由器怎样设置DDNS 开启DDNS操作方法步骤
  8. 方志仅占古籍数量十分之一,在家谱编修中却举足轻重,方志凭什么
  9. Secondary NameNode:究竟是什么?
  10. 工程师视角的手游SDK
  11. 分页插件Kaminari
  12. 【华为云技术分享】漫谈LIteOS-物联网操作系统介绍
  13. 立方尾不变-Python
  14. httpmember.php,PHPMyWind 5.1 /member.php 远程密码修改漏洞
  15. Java多线程 信号量和屏障实现控制并发线程数量,主线程等待所有线程执行完毕2
  16. 关键词推广怎么做比较好?抖音宣传做关键词推广有哪些好的方法
  17. 率土之滨服务器进备战区维护多久,率土之滨备战区维护,备战区为什么不拆战法...
  18. How to edit registry via CMD command
  19. Mybatis 实现原理之 一二级缓存
  20. android开源项目 Google code

热门文章

  1. 天池龙珠计划SQL_TASK2
  2. IMX6ULL驱动开发前奏三:根文件系统构建步骤明细
  3. 09亚联入围选手名单
  4. Open CV入门教程--电子书高清免费下载
  5. 针对暴力裁员一事,网易向员工致歉 对事件的时间线进行了梳理
  6. 苹果Mac怎样强制退出冻结的菜单栏应用程序?
  7. 关于在用爬虫时,获取的页面不全的一种可能性
  8. 车牌识别 easypr 【ubuntu系统配置】
  9. Ubuntu下使用动画壁纸 LiveWallpaper
  10. 如何沿着某一直线绘制特定物理场(高程、负荷场)剖面(Arcgis\GMT\MATLAB)