14

when using epoll_ctl(), I found that the third parameter "fd" is another file descriptor besides the epoll file descriptor "epfd". And I saw an example like this:

event.data.fd = sfd; //sfd is a fd for listening
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);

As I saw, file descriptor in event.data.fd is the same as the third parameter in epoll_ctl, why need to pass this descriptor twice? is there any difference?

realjin
  • 1,485
  • 1
  • 19
  • 38
  • 1
    You may consider the implementation didn't do the assignment for you. Sometimes low level C system call rely on programmers. The event is not always needed, e.g. during EPOLL_CTL_DEL the event is ignored but you cannot give a NULL pointer as argument. – Ken Cheung Feb 17 '12 at 09:40

1 Answers1

20

Actually you don't have to set event.data.fd. It's a union, you can set other members. When epoll_wait returns you get the event.data associated with the descriptor that became interesting:

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

Which means you're completely free not to put anything in fd and put something in ptr instead (for example).

In conclusion, epoll_ctl can't rely on the fact you'll fill fd in, that's why it has a separate explicit parameter.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • 3
    The `fd` you pass to `epoll_ctl` is the file descriptor you wish to get events for. The `fd` in `event.data` is strictly for your use -- the system ignores it and you can use it for any purpose. – David Schwartz Feb 17 '12 at 09:41
  • 8
    I've actually seen a lot of code that puts the fd in the epoll_data structure, only to use that fd as an index into a table that holds a pointer to the application's structure associated with that socket -- a structure that also contains the fd. Apparently, they didn't realize they could use the `ptr` member instead of `fd` and save the lookup. – David Schwartz Feb 17 '12 at 09:50
  • 8
    OK, I understand --- the fd in epoll_data is not intended to be used by the system but by myself. – realjin Feb 17 '12 at 09:56
  • To clarify, the ev that is epoll_ctl(..ADD..) is "spit back out" when you epoll_wait() and there's an event? @DavidSchwartz i.e., can you "store" the pointers in epoll? – awe lotta Jun 30 '23 at 01:16
  • @awelotta You can store whatever is useful to you in that union. Using `ptr` to store a pointer to some object or structure with information about the context is common. – David Schwartz Jul 04 '23 at 11:35
  • @DavidSchwartz I was just wondering if you risked memory leak if you stored malloc'd pointers (i.e. is it sufficient to just make sure you `epoll_wait`'d every epoll fd?) – awe lotta Jul 07 '23 at 00:59
  • @awelotta So long as you `free` them when you are done with them, there's no risk of a leak. – David Schwartz Jul 07 '23 at 03:26