By francis_hao    Aug 5,2017

 

APUE讲多路转接的章节介绍了select、pselect和poll函数。而epoll是linux内核在2.5.44引入的。在glibc 2.3.2添加了支持。

 

epoll_create – 打开一个epoll文件描述符

epoll_ctl – 控制epoll文件描述符接口

epoll_wait – 在epoll文件描述符上等待一个I/O事件

概述

#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);

 

描述

epoll_create()

创建一个epoll(7)实例,返回指向这个实例的文件描述符,这个文件描述符会被之后的epoll函数使用,当该文件描述符不再需要的时候,应当使用close(2)关闭。当所有指向同一个epoll实例的文件描述符都被关闭后,内核会销毁该实例,释放分配的资源以复用。

参数size原本用来告诉内核要添加到epoll实例中文件描述符的数量,内核用这个参数作为一个大概的分配空间大小的指示,以存放描述事件的结构体数据。但是从内核2.6.8之后,这个参数就不再需要了,内核会动态的分配需要的空间大小。但是参数size必须依然是大于0的数,以确保新的epoll函数运行在旧的内核上时能向后兼容。

函数执行成功返回非负的文件描述符,若有错误则返回-1,而且errno被置为相应的值以指示该错误。

epoll_ctl()

这个系统调用对由文件描述符epfd指定的epoll实例执行控制操作,同时需要指定目标文件描述符fd,和对其的操作op。有效的op参数如下

op

说明

EPOLL_CTL_ADD

注册目标文件描述符fd到epoll实例,并关联事件event

EPOLL_CTL_MOD

改变关联到目标文件描述符fd的事件event

EPOLL_CTL_DEL

从epoll实例移除目标文件描述符,event被忽略,可以是NULL

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 events */
    epoll_data_t data;        /* User data variable */
};

成员events可以是以下常量的按位或集:

events

说明

EPOLLIN

关联的文件可以进行read(2)操作

EPOLLOUT

关联的文件可以进行write(2)操作

EPOLLRDHUP

(since Linux 2.6.17)

对方关闭了流套接字连接,or shut down writing half of connection。

EPOLLPRI

有紧急数据可以进行read(2)操作

EPOLLERR

在关联的文件描述上发生了错误,epoll_wait(2)总会等待这一事件,因此无需对此位置位

EPOLLHUP

关联的文件描述符挂起(Hang up)了,poll_wait(2)总会等待这一事件,因此无需对此位置位

EPOLLET

为关联的文件描述符设置边沿触发,默认的行为是电平触发(Level Triggered)

EPOLLONESHOT

(since Linux 2.6.2)

为关联的文件描述符设置单次行为,这意味着该文件描述符一旦由epoll_wait(2)返回一次事件,就会被内部失能,再不会有其他事件被报告,用户程序必须调用epoll_ctl()函数,使用EPOLL_CTL_MOD命令重新关联event

函数执行成功返回0,错误返回-1,而且errno被置为相应的值。

epoll_wait()

该系统调用等待由文件描述符epfd指定的epoll实例上的事件,由events指向的内存区域包含了准备好的事件。至多有maxevents个事件由epoll_wait()返回,该值必须大于0。timeout参数指定epoll_wait()将最多阻塞多长时间(ms)。指定-1使epoll_wait()一直等待,直到有准备好的事件,而指定0使epoll_wait()立即返回,即使没有事件准备好。

函数执行成功返回准备好的文件描述符的数量,如果在timeout时间内仍然没有文件描述符准备好则返回0,错误返回-1,而且errno被置为相应的值。

 

两点要注意:

  1. epoll_ctl(int epfd, int op, int fd, struct epoll_event *event),fd和event的fd必须同时赋值
  2. close不能使文件描述符从epoll中移除,必须使用epoll_ctl的EPOLL_CTL_DEL(此情况是已经有数据在缓存里,还未调用epoll_wait,此时先close再调用epoll_wait的情况)

 

实例

一个简单的用法:

#include <sys/epoll.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
    int epoll_fd;
    int fds_num;
    char str[50]={0};
    struct epoll_event ev_in,ev_out;
    fds_num =
0;

    epoll_fd = epoll_create(2);
/*this 'size' argument is ignored*/
    if
(-1
== epoll_fd){
        perror("epoll_create");
        return
-1;
    }
    memset(&ev_in,
0,
sizeof
(ev_in));
    memset(&ev_out,
0,
sizeof
(ev_out));
    ev_in.events = EPOLLIN;
    if
(-1
== epoll_ctl(epoll_fd, EPOLL_CTL_ADD,
0,
&ev_in)){/*Register the target file descriptor 0,that is stdin*/
        perror("epoll_ctl");
        return
-1;
    }

#define TIMEOUT 20
    while(1){
        fds_num = epoll_wait(epoll_fd,
&ev_out,
5, TIMEOUT*1000);
        //fds_num = epoll_wait(epoll_fd, &ev_out, 5, -1);
        if
(-1
== fds_num){
            perror("epoll_wait");
            return
-1;
        }else
if
(0
== fds_num){
            printf("none data within %u s\n",TIMEOUT);
            return
0;
        }
        if
(
0
== ev_out.data.fd){
            if
((ev_out.events & EPOLLIN)
!=
0){
                //printf("events is %x\n",ev_out.events);
                if
(-1
== read(0, str,
50)){
                    perror("read");
                    return
-1;
                }
                printf("%s",str);
                memset(str,
0
,sizeof
(str));
            }
        }else{
            printf("%d\n",ev_out.data.fd);
        }
    }
    return
0;
}

执行结果:

程序源码在github上,可以直接clone编译测试:
epoll

 

 


本文由
刘英皓 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处:
转载自:http://www.cnblogs.com/yinghao1991/p/7291912.html

 

 

参考

【1】man 7 epoll

【2】man epoll_create

【3】man epoll_ctl

【4】man epoll_wait

 

I/O多路转接-epoll的更多相关文章

  1. Linux下I/O多路转接之epoll(绝对经典)

    epoll 关于Linux下I/O多路转接之epoll函数,什么返回值,什么参数,我不想再多的解释,您不想移驾,我给你移来: http://blog.csdn.net/colder2008/artic ...

  2. 【Nginx】I/O多路转接之select、poll、epoll

    当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解决方案有以下几种: 1.使用多进程或 ...

  3. 高级I/O之I/O多路转接——pool、select

    当从一个描述符读,然后又写到另一个描述符时,可以在下列形式的循环中使用阻塞I/O: ) if (write(STDOUT_FILENO, buf, n) != n) err_sys("wri ...

  4. IO多路转接select和poll

    select IO多路复用的设置方法与信号的屏蔽有点相似: 信号屏蔽需要先设定一个信号集, 初始化信号集, 添加需要屏蔽的信号, 然后用sigprocmask设置 IO多路转接需要先设定一个文件描述符 ...

  5. I/O多路转接 --- UNIX环境高级编程

    I/O多路转接技术:先构造一张有关描述符的列表,然后调用一个函数,知道这些描述符中的一个已准备好进行I/O时,给函数才返回.在返回时,它告诉进程哪些描述符已准备好可以进行I/O. poll.selec ...

  6. I/O多路转接模型

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  7. Linux下I/O多路转接之select --fd_set

    fd_set 你终于还是来了,能看到这个标题进来的,我想,你一定是和我遇到了一样的问题,一样的疑惑,接下来几个小时,我一定竭尽全力,写出我想说的,希望也正是你所需要的: 关于Linux下I/O多路转接 ...

  8. UNIX环境高级编程——I/O多路转接(select、pselect和poll)

    I/O多路转接:先构造一张有关描述符的列表,然后调用一个函数,直到这些描述符中的一个已准备好进行I/O时,该函数才返回.在返回时,它告诉进程哪些描述符已准备好可以进行I/O. poll.pselect ...

  9. select函数与I/O多路转接

    select函数与I/O多路转接 相作大家都写过读写IO操作的代码,例如从socket中读取数据可以使用如下的代码: while( (n = read(socketfd, buf, BUFSIZE) ...

随机推荐

  1. 1. tty终端接收数据原理

    1. 串口接收数据原理(以“ls”命令为例) (1) 每个终端设备都有一个接收缓冲区,保存原始数据.shell程序一直在休眠,等待合适的字符: (2) 串口接收到'l'字符,把它保存下来: (3) 串 ...

  2. python 中 pynlpir错误 Cannot Open Configure file pynlpir\Data\Configure.xml 解决

    在用python做分词.数据处理的时候,想调用pynlpir库,pynlpir.open()时出现错误,更新一下授权文件还是错误, 仔细一看错误是:Cannot Open Configure file ...

  3. (数据科学学习手札11)K-means聚类法的原理简介&Python与R实现

    kmeans法(K均值法)是麦奎因提出的,这种算法的基本思想是将每一个样本分配给最靠近中心(均值)的类中,具体的算法至少包括以下三个步骤: 1.将所有的样品分成k个初始类: 2.通过欧氏距离将某个样品 ...

  4. 【目录】Spring 源码学习

    [目录]Spring 源码学习 jwfy 关注 2018.01.31 19:57* 字数 896 阅读 152评论 0喜欢 9 用来记录自己学习spring源码的一些心得和体会以及相关功能的实现原理, ...

  5. SVN 使用时的小错误

    在使用SVN的时候总是出现一些小问题,今天又出现了一个,诶,分享一下吧!  Error:(个人文件夹名http://www.qdjhu.com/anli_xq/f_wancheng.php)  is ...

  6. CS229 1

    1.机器学习 机器学习是工具,具体应用到某个实际场景下,才是目的. 2.分类 a 监督学习,包括回归(regression),分类(classification).回归问题,数据可以是连续或者离散,分 ...

  7. Jenkins - 持续集成部署

    1. 安装svn:用于checkout源码 (1)yum 安装:yum -y install subversion (2)查看svn版本信息:svnserver --version 2. 安装jdk ...

  8. C 计算金额

    #include <stdio.h> int main(int argc, char **argv) { \\定义两个变量 a金额 z跟票面 int a=0; int z=0;\\ 输入金 ...

  9. c#程序中的AssemblyInfo.cs

    在asp.net中有一个配置文件AssemblyInfo.cs主要用来设定生成的有关程序集的常规信息dll文件的一些参数,下面是默认的AssemblyInfo.cs文件的内容具体介绍 //是否符合公共 ...

  10. lintcode-95-验证二叉查找树

    95-验证二叉查找树 给定一个二叉树,判断它是否是合法的二叉查找树(BST) 一棵BST定义为: 节点的左子树中的值要严格小于该节点的值. 节点的右子树中的值要严格大于该节点的值. 左右子树也必须是二 ...