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;
}
上一篇: #define 和typedef的区别