epoll的用法

24 篇文章 0 订阅

示例如下:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <unistd.h>
#include <cstdint>

/* epoll event callback function */
void evt_proc(struct epoll_event *trig_event);
/* write fd thread,trigger EPOLLIN event */
void *thread_a(void *arg);
/* callback function pointer */
typedef void (*callback_fun)(epoll_event*);

/* epoll data */
struct EPOLL_DATA
{       
        /* file descriptor */
        int fd;
        /* callback pointer */
        callback_fun clb_func;
};

int main(void)
{
        /* create a file descriptor for event notification */
        int evtfd=eventfd(0,0);
        /* open an epoll file descriptor */
        int epfd = epoll_create(1);
        if (epfd < 0)
        {
                printf("epoll_create() error,%d:%s!\n", errno, strerror(errno));
                exit(errno);
        }

        EPOLL_DATA epldata;
        epldata.fd=evtfd;
        epldata.clb_func=evt_proc;
        epoll_event ep_ev;
        /*
        The associated file is available for read operations,
        and sets the Edge Triggered behavior for the associated file descriptor
        */
        ep_ev.events=EPOLLIN|EPOLLET;
        ep_ev.data.ptr=&epldata;

        /* Register the target file descriptor fd on the epoll instance */
        epoll_ctl(epfd, EPOLL_CTL_ADD, evtfd, &ep_ev);

        /* available events */
        epoll_event trig_event;
        /* the number of milliseconds that epoll_wait() will block */
        int timeout = 500;

        /* create thread to write evtfd */
        pthread_t a_thread;
        int crt_res=pthread_create(&a_thread,nullptr,thread_a,(void*)&evtfd);
        if(crt_res!=0)
        {
                printf("create thread error,%d:%s!\n", errno, strerror(errno));
        }

        int evt_wt_res=0;
        while (true)
        {
                evt_wt_res = epoll_wait(epfd, &trig_event, 1, timeout);
                switch (evt_wt_res)
                {
                case 0:
                        /* no file descriptor became ready */
                        /*printf("epoll_wait timeout\n");*/
                        break;
                case -1:
                        /* some error occurred */
                        printf("epoll_wait error!\n");
                        break;
                default:
                        callback_fun pfnc=((EPOLL_DATA*)(trig_event.data.ptr))->clb_func;
                        (*pfnc)(&trig_event);
                        break;
                }
        }
        close(epfd);
        close(evtfd);
        return 0;
}

void evt_proc(struct epoll_event *trig_event)
{
        if (trig_event->events & EPOLLIN)
        {
                uint64_t int_val=-1;
                int res=read(((EPOLL_DATA*)(trig_event->data.ptr))->fd,&int_val,sizeof(uint64_t));
                if(res<0)
                {
                        printf("read fd error:fd=%d,%d:%s!\n",((EPOLL_DATA*)(trig_event->data.ptr))->fd,errno, strerror(errno));
                }
                else
                {
                        printf("read value=%ld\n",int_val);
                }
        }
        else
        {
                printf("unknown event!\n");
        }
}

void *thread_a(void *arg)
{
        int fd=*(int*)arg;
        for(uint64_t i=0;i<50;++i)
        {
                int res=write(fd,&i,sizeof(uint64_t));
                if(res<0)
                {
                        printf("write fd error,%d:%s!\n", errno, strerror(errno));
                }
                sleep(1);
        }
}

编译运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`epoll`是一个Linux系统调用,它允许程序监听一个文件系统的变化,即文件的读写完成或可写事件等。这通常对于多路复用器或网络编程特别有用,因为它们需要监控多个套接字的操作,并且对于同时到达的事件,需要进行选择并执行适当的操作。 下面是一些基本的用法: 1. **创建epoll实例**:使用`epoll_create()`函数创建一个新的epoll实例。这个函数返回一个文件描述符,可以用于后续的调用。 ```c int epoll_create(int size); ``` 其中,`size`参数指定了文件描述符数组的大小。 2. **添加文件描述符到epoll**:使用`epoll_ctl()`函数将文件描述符添加到epoll实例中。添加的方式有两种: * `EPOLL_CTL_ADD`:添加新的文件描述符到epoll实例。 * `EPOLL_CTL_MOD`:修改已存在的文件描述符在epoll实例中的行为。对于已经添加的文件描述符,必须使用这个选项。 ```c int epoll_ctl(int epollfd, int op, int fd, struct epoll_event *event); ``` 其中,`epollfd`是创建的epoll实例的文件描述符,`op`是操作类型(通常为`EPOLL_IN`或`EPOLL_OUT`),`fd`是要添加的文件描述符,`event`是一个结构体,包含了要添加的文件描述符的行为信息。 3. **读取事件**:使用`epoll_wait()`函数读取事件。这个函数会阻塞当前进程,直到有事件发生或者超时。它返回一个文件描述符数组,每个元素对应一个新的事件。返回的文件描述符的数量可以是一个固定的值,也可能是大于之前设定的值的值。可以通过遍历数组获取具体。的事件 ```c int epoll_wait(int epollfd, struct epoll_event *events, int maxevents, int timeout); ``` 注意,调用此函数后返回的文件描述符数组的指针可能会在之后的调用中被更改,以反映在事件之间发生的更改。 4. **清理**:当不再需要epoll实例时,需要调用`close()`函数关闭它。这样可以释放与该实例关联的资源。 这就是基本的`epoll`的使用方法。请注意,在实际使用中,还需要考虑一些其他的因素,例如错误处理、并发控制等。此外,为了正确使用`epoll`,你需要理解事件如何被表示以及如何处理这些事件。具体的使用细节和例子可以在Linux内核源代码中找到。 在使用这些函数时,你需要注意它们的返回值和错误代码,以确保你的程序在发生错误时能够正确地处理。另外,你也需要根据你的应用程序的需求来配置和选择合适的事件类型和行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值