1. 基本概念

  当程序进行IO时,如果数据尚未准备好,那么IO将处于阻塞状态。当某个进程有多个打开的文件,比如socket,那么其后的所有准备好读写的文件将受到阻塞的影响而不能操作。不借助线程,单一进程无法在同一时间服务多个文件描述符。非阻挡式IO可以作为一个解决方案,但是效率并不高。首先进程需要不断发IO请求,其次,如果程序可以休眠,让出CPU将提高效率。多任务式IO是在其中任何一个文件描述符就绪时收到通知,此时IO将不会受到阻挡,其余时间处于休眠状态,将CPU资源让给别的进程。

  为了实现I/O多路复用,epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率。

2. api

#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
  • int epoll_create(int size) [创建句柄]

  创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

  函数生成一个epoll专用的文件描述符。它其实是在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件。size就是你在这个epoll fd上能关注的最大socket fd数。随你定好了。只要你有空间。可参见上面与select之不同

  • int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)[事件注册函数]

  epoll的事件注册函数,对比select()函数,select()是在监听事件时告诉内核要监听什么类型的事件,而epoll是在调用epoll_ctl函数的时候,先注册要监听的事件类型。

  epfd:epoll_create()的返回值;
  op:表示要进行的操作,操作的动作使用了宏定义:

    1. EPOLL_CTL_ADD: 注册新的fd到epfd中;
    2. EPOLL_CTL_MOD: 修改已经注册的fd的监听事件;
    3. EPOLL_CTL_DEL: 删除epfd中的一个fd;

  fd:关联的文件描述符,表示需要监听的fd;
  event:指向epoll_event的指针,告诉内核需要监听什么事件,epoll_event的结构如下:

struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};

events描述事件类型,使用了宏定义:

  1. EPOLLIN:表示对应的文件描述符可以读(包括对端socket正常关闭);

  2. EPOLLOUT: 表示对应的文件描述符可以写;

  3. EPOLLPRI: 表示对应的文件描述符有紧急的数据可读(表示有外数据到来);

  4. EPOLLHUP: 表示对应的文件描述符被挂断;

  5. EPOLLET: 将EPOLL设置为边缘触发(Edge Triggered)模式;

  6. EPOLLONESHOT: 只监听一次事件,当监听玩这次事件之后,如果还需要继续监听,需要再次将该socket加入EPOLL队列中。

  • int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout) [等待事件触发]

  等待事件的产生,类似于select()调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1表示不确定)。该函数返回需要处理的事件数目,如返回0表示已超时。

3.epoll工作模式

  epoll对文件描述符的操作有两种模式:LT(level trigger,水平触发)和ET(edge trigger,边缘触发)。

  LT模式:水平触发是缺省的工作方式。当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件(进行IO操作)。下次调用epoll_wait时,会再次响应应用程序并通知此事件。由于对于描述事件符在处理前会进行多次通知,因此出错的概率小;

  ET模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,此时它会假设你知道文件描述符已就绪,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件,直到做了一定操作导致该文件描述符再次变为未就绪状态。但是如果一直对该fd进行IO操作()

  ET模式在很大程度上减少了epoll事件被重复触发的次数,因此效率要比LT模式高。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。

unix网络编程——I/O多路复用之epoll的更多相关文章

  1. UNIX网络编程——epoll 的accept , read, write(重要)

    在一个非阻塞的socket上调用read/write函数,返回EAGAIN或者EWOULDBLOCK(注:EAGAIN就是EWOULDBLOCK). 从字面上看,意思是: EAGAIN: 再试一次 E ...

  2. unix网络编程 str_cli epoll 非阻塞版本

    unix网络编程 str_cli epoll 非阻塞版本 unix网络编程str_cli使用epoll实现讲了使用epoll配合阻塞io来实现str_cli,这个版本是配合非阻塞io. 可以看到采用非 ...

  3. unix网络编程str_cli使用epoll实现

    unix网络编程str_cli使用epoll实现 unix环境高级编程中也有这个函数,都是为了讲解IO多路转接.从本质上来看epoll就是一个改善了的select和poll,本质没发生任何变化,对于构 ...

  4. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

  5. UNIX网络编程——并发服务器(TCP)

    在迭代服务器中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现. 网络服务器通常用fork来同时 ...

  6. 《Unix 网络编程》14:高级 I/O 函数

    高级 I/O 函数 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ...

  7. UNIX网络编程——getsockname和getpeername函数

    UNIX网络编程--getsockname和getpeername函数   来源:网络转载   http://www.educity.cn/linux/1241293.html     这两个函数或者 ...

  8. 【LINUX/UNIX网络编程】之简单多线程服务器(多人群聊系统)

    RT,Linux下使用c实现的多线程服务器.这个真是简单的不能再简单的了,有写的不好的地方,还希望大神轻拍.(>﹏<) 本学期Linux.unix网络编程的第四个作业. 先上实验要求: [ ...

  9. 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)

    RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三  多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...

随机推荐

  1. 克隆虚拟机及配置yum源的步骤及讲解(Hadoop基础)

    1.克隆虚拟机 找一台需要克隆的虚拟机但虚拟机必须在关机下进行,(建议将前期Linux环境 配置完成) 在VMware中右键虚拟机找到克隆的选项.   点击克隆 可以克隆他的快照(提前做快照)或者是克 ...

  2. Apache 流框架 Flink,Spark Streaming,Storm对比分析(二)

    本文由  网易云发布. 本文内容接上一篇Apache 流框架 Flink,Spark Streaming,Storm对比分析(一) 2.Spark Streaming架构及特性分析 2.1 基本架构 ...

  3. python3爬虫-下载网易云音乐,评论

    # -*- coding: utf-8 -*- ''' 16位随机字符的字符串 参数一 获取歌曲下载地址 "{"ids":"[1361348080]" ...

  4. go 数组、切片

    数组定义      // 标准 ]], , , , } fmt.Println("a", a) // 自动推导类型 b := [], , , , } fmt.Println(&qu ...

  5. QuestaSim 中文注释乱码

    在QuestaSim按如下顺序打开对应窗口, Tools -> Edit Preferences -> By Name -> Find 输入 encoding搜索对应项,将其valu ...

  6. 使用maven构建scala项目

    eclipse安装scala插件和m2e-scala并不是支持的很好,因此使用maven创建scala工程的时候,IDEA可谓是最好的开发利器. 1. 创建工程之前的准备 2. IDEA界面创建Sca ...

  7. 手把手教你开发chrome扩展

    转载:http://www.cnblogs.com/walkingp/archive/2011/04/04/2003875.html 手把手教你开发chrome扩展一:开发Chrome Extenst ...

  8. 20155325 Exp1 PC平台逆向破解(5)M

    Exp1 PC平台逆向破解(5)M 阶段性截图 基础知识 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码 汇编指令 作用 机器码 NOP "空指令".执行到NOP ...

  9. 如何查看PostgreSQL的checkpoint 活动

    磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL基础知识与基本操作索引页    回到顶级页面:PostgreSQL索引页 作者:高健@博客园 luckyjackgao@g ...

  10. mfc 带参数的构造函数

    知识点 默认的构造函数 带参数的构造函数 重载构造函数 一.默认的构造函数 二.带参数的构造函数 三.重载构造函数 class Tdate { public: int year;//年 int mon ...