欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

epoll_data 结构体问题

程序员文章站 2024-03-23 11:40:34
...

学习epoll使用的过程中,了解到epoll_data中有一个指针ptr可供自定义使用,结构定义如下:

typedef union epoll_data
{
  void *ptr;
  int fd;
  uint32_t u32;
  uint64_t u64;
} epoll_data_t;

epoll_event结构体定义如下:

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

 于是我做了如下操作:

struct myevent_s {
    int fd;
    int events;
    void *arg;
    void (*call_back)(int fd, int events, void *arg);
    int status;
    char buf[256];
    int len;
    long last_active;
};


struct epoll_event ev = {0};
struct epoll *evptr;
ev.events = EPOLLIN; //监听定时器读事件,当定时器超时时,定时器描述符可读。
ev.data.fd = efd;//efd是我创建的一个对象标识符
ev.data.ptr=&g_event;

//....
//....epoll操作,此处略去

ret = read(evptr->data.fd, &value, sizeof(uint64_t));

然而总是报错,read返回-1。单步调试后发现在给ev.data.xxx赋值时,之前赋的值总会变化。仔细看了定义后才看到,data是个union, 不是struct。union是各项共用一段内存,所以后面改动了前面也会跟着改动了。

 

附上我的测试代码:

 #include <sys/timerfd.h>
 #include <sys/epoll.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdio.h>
 #include<errno.h>
 #include <time.h>
 #define TIME_MAX 2
 //#define printf(fmt, arg...) printf(""fmt, ##arg)

struct myevent_s {
    int fd;
    int events;
    void *arg;
    void (*call_back)(int fd, int events, void *arg);
    int status;
    char buf[256];
    int len;
    long last_active;
};
//然后在epoll_wait()的第二个参数中的data.ptr会原封不动的把上边的g_event返回给我们,所以我们可以利用这个ptr传参。

 int main() {
     int tfd;//定时器描述符
     int efd; //epoll描述符
     int fds, ret;
     uint64_t value;
     struct epoll_event ev = {0};
     struct epoll_event *evptr;
     struct itimerspec time_intv; //用来存储时间

     tfd = timerfd_create(CLOCK_MONOTONIC, 0); //创建定时器
     if(tfd == -1) {
         printf("create timer fd fail \r\n");
         return 0;
     }
     time_intv.it_value.tv_sec = TIME_MAX; //设定2s超时
     time_intv.it_value.tv_nsec = 0;
     time_intv.it_interval.tv_sec = time_intv.it_value.tv_sec; //每隔2s超时
     time_intv.it_interval.tv_nsec = time_intv.it_value.tv_nsec;
     printf("timer start ...\n");
     timerfd_settime(tfd, 0, &time_intv, NULL);//启动定时器
     efd = epoll_create1(0); //创建epoll实例
     if (efd == -1) {
         printf("create epoll fail \r\n");
         close(tfd);
         return 0;
     }
     evptr = (struct epoll_event *)calloc(1, sizeof(struct epoll_event));
     if (evptr == NULL) {
         printf("epoll event calloc fail\n");
         close(tfd);
         close(efd);
         return 0;
     }
     struct myevent_s g_event;
     sprintf(g_event.buf, "hello world", 8);
     g_event.fd = tfd;
     ev.events = EPOLLIN; //监听定时器读事件,当定时器超时时,定时器描述符可读。
     ev.data.ptr=&g_event;
     epoll_ctl(efd, EPOLL_CTL_ADD, tfd, &ev); //添加到epoll监听队列中
     while(1) {
         fds = epoll_wait(efd, evptr, 1, -1); //阻塞监听,直到有事件发生
         if(evptr[0].events & EPOLLIN){
             ret = read(((myevent_s*)(evptr->data.ptr))->fd, &value, sizeof(uint64_t));
             if (ret == -1)
                 printf("read return -1, errno :%d \r\n", errno);
             else printf("*** timer up: %s  *** \n", ((myevent_s*)(evptr->data.ptr))->buf);
         }
     }
     return 0;
 }

 

相关标签: epoll