epoll中的data聯合體怎樣使用的問題

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)等套接字函數收數據。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章