IO多路复用之epoll

一、epoll函数族

1. 函数epoll_creat: 该函数生成一个epoll专用的文件描述符

#include <sys/epoll.h>
int epoll_creae(int size);  //epoll上能关注的最大描述符数

 

2. epoll_ctl:用于控制某个epoll文件描述符事件,可以注册、修改、删除

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

参数:

  • efd:epoll_create函数的返回值
  • op:对该监听红黑树所做操作
  • fd:待监听的fd
  • event:struct epoll_event 结构体
typedef union epoll_data 
{
    void*      ptr;
    int        fd;  //对应监听的fd
    uint32_t   u32;
    uint64_t   u64;
} epoll_data_t;

struct epoll_event 
{
    uint32_t     events;      /* epoll事件 */
    epoll_data_t data;        /* 用户数据 */
};

 

3. 等待IO事件发生 - 可以设置阻塞的函数

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

参数:

  • efds:epoll_create函数的返回值
  • events:传出参数【数组】满足监听条件的哪些fd结构体
  • maxevents:数组元素的总个数(1024) struct epoll_events [1024]:

 

二、LT和ET模式

epoll对文件描述符的操作方式有两种工作模式:LT模式(Level Trigger,水平触发) 和ET模式(Edge Trigger,边缘触发)。

  •  LT模式:当epoll_wait检测到其上有事件发生并将此事件通知应用程序后,应用程序可以不立即处理该事件,这样,当应用程序下一次调用epoll_wait时,epoll_wait还会向应用程序通告此事件,直到该事件被处理。((缓冲区剩余未读尽的数据会导致epoll_wait返回. )
  • ET模式:当epoll_wait检测到其上有事件发生并将此事件通知应用程序后,应用程序必须立即处理该事件,因为后续的epoll_wait调用将不在向应用程序通告此事件。

1. 水平触发
 对于读操作

  • 只要缓冲内容不为空,LT模式返回读就绪。

 对于写操作

  • 只要缓冲区还不满,LT模式会返回写就绪。

2. 边缘触发
 对于读操作

  • 当缓冲区由不可读变为可读的时候,即缓冲区由空变为不空的时候。
  • 当有新数据到达时,即缓冲区中的待读数据变多的时候。
  • 当缓冲区有数据可读,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLIN事件时。

对于写操作

  • 当缓冲区由不可写变为可写时。
  • 当有旧数据被发送走,即缓冲区中的内容变少的时候。
  • 当缓冲区有空间可写,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLOUT事件时。

三、代码清单

1. 测试代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>

#define MAXLINE 10

int main(int argc, char *argv[])
{
    int efd, i;
    int pfd[2];
    pid_t pid;
    char buf[MAXLINE], ch = 'a';

    pipe(pfd);
    pid = fork();

    if (pid == 0)  //子写
    {             
        close(pfd[0]);
        while (1) 
        {     
            for (i = 0; i < MAXLINE/2; i++) //aaaa\n
                buf[i] = ch;
            buf[i-1] = '\n';
            ch++;
            
            for (; i < MAXLINE; i++) //bbbb\n
                buf[i] = ch;
            buf[i-1] = '\n';
            ch++;
            
            write(pfd[1], buf, sizeof(buf)); //aaaa\nbbbb\n
            sleep(5);
        }
        close(pfd[1]);
    } 
    else if (pid > 0)  //父读
    {       
        struct epoll_event event;
        struct epoll_event resevent[10];  //epoll_wait就绪返回event
        int res, len;

        close(pfd[1]);
        efd = epoll_create(10);

        event.events = EPOLLIN | EPOLLET;    // ET 边沿触发
        //event.events = EPOLLIN;            // LT 水平触发 (默认)
        event.data.fd = pfd[0];
        epoll_ctl(efd, EPOLL_CTL_ADD, pfd[0], &event);

        while (1) 
        {
            res = epoll_wait(efd, resevent, 10, -1);
            printf("res %d\n", res);
            if (resevent[0].data.fd == pfd[0]) 
            {
                len = read(pfd[0], buf, MAXLINE/2);
                write(STDOUT_FILENO, buf, len);
            }
        }
        close(pfd[0]);
        close(efd);
    } 
    else 
    {
        perror("fork");
        exit(-1);
    }
    return 0;
}

 

 


 

 

  •  
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值