Сначала создайте новый kqueue:
int kq=kqueue();
Теперь зарегистрируйте свой fd в kq:
struct kevent kev;
kev.ident=your_fd;
kev.flags=EV_ADD | EV_CLEAR;
kev.filter=EVFILT_READ;
kev.fflags=0;
kev.data=0;
kev.udata=&your_data;
int res=kevent(kq,&kev,1,0,0,0);
Наконец, дождитесь поступления данных в ваш сокет:
struct kevent res_kevs[5];
int res=kevent(kq,0,0,res_kevs,5,0);
После возврата res_kevs[i].ident
будет содержать дескриптор вашего сокета, res_kevs[i].data
- количество байтов, готовых для чтения.
См. Man kevent для более подробной информации и возможностей.