epoll中的data联合体怎样使用的问题

epoll结构体中的data联合体包含void *ptr,用于链接到自定义结构体。正确做法是创建一个包含fd等信息的结构体st,将st的指针赋值给ptr。当epoll_wait返回时,通过(void*)evs[index].data.ptr获取结构体指针,以此判断数据来源并进行相应操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、epoll结构体的成员data其实是一个结构体,具体如下:

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 */
};

那么我们在编程时就不应该同事使用 epoll_data联合体中的两个成员,比如,有时为了方便确定那个描述符就绪,以及获取自己定义的一些内容,我们常常 ptr和fd同事使用,结果发现程序会崩溃。比如下面一段文字是overstack上面的一个提问:

I am having an increasingly hard time using the void *ptr in the epoll_event. I can just link this to a struct? For example, can I do something like this? Because I am trying todo something like this but it does not work, the first loop on the listen socket is good, but after another event comes in it crashes. Can someone help me out in understanding how to use data.ptr?

struct client { 
int fd; 
int connection_status;
};

struct epoll_event *events = NULL;
struct epoll_event ev;
struct client *c = new client;
struct client *event_c = NULL;

c.fd = (socket);

int efd = epoll_create1(0);
ev.data.fd = c.fd; //使用了fd
ev.events = EPOLLIN;
ev.data.ptr = c;//又使用了ptr,所以肯定有问题
epoll_ctl ( efd , EPOLL_CTL_ADD , c.fd , &ev );

events = (struct epoll_event*)calloc ( XXX , sizeof event );

while(1) {
    int n = epoll_wait ( efd , events , XXX , -1 ); 
    for ( int i = 0 ; i  < n ; i++ ) {
        event_c = (struct client*) events[i].data.ptr;
        cout << "SOCKET: " << event_c->fd << endl;

        if (c->fd == events[i].data.fd ) {
            struct client *new_c = new client;
            struct epoll_event new_ev;
            struct sockaddr inaddr;
            sockletn_t in_len;
            int nfd = accept ( c->fd , &inaddr , &in_len );
            /* make socket non-blocking ... / error checking */
            new_c->fd = nfd;
            new_c->connection_status = 1;
            new_ev.data.fd = nfd;
            new_ev.events = EPOLLIN;
            new_ev.data.ptr = client;//应该是:<span style="font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;">new_c</span>
            int r = epoll_ctl ( efd , EPOLL_CTL_ADD , nfd , &new_ev );
            continue;
         } else {
            ssize_t count;
            char buf[512];
            int count = read ( events[i].data.fd , buf , sizeof buf );
            // ... error checking blah blah blah

            int rc = write ( 1 , buf , count );
        }
    }
}

下面是回答:

The void *ptr and int fd both are inside a union inside the struct epoll_event. You should use either of them not both. Hence in your struct, add the field for fd as well and only link pointer to the struct in the ptr field of the epoll_event. This way when you get back your pointer then get the fdfrom it for further use.


解决方法:将fd等所有我们感兴趣的东西全部放到一个结构体st里面,然后将结构体指针pst赋值给ptr,当epoll_wait()返回时,先:ptr=(st*)((evs[index].data.ptr)),根据pst里面的fd就可以知道是哪个套接字发送过来的数据了。然后再条用recv(ptr->fd)等套接字函数收数据。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值