a scalable I/O event notification mechanism used in Linux programming to efficiently monitor multiple file descriptors to see if I/O is possible on any of them.
(The more recent epoll_create1 (2) extends the functionality of epoll_create (2).)
epoll 现在是线程安全 的,而 select 和 poll 不是。
epoll 基于事件驱动,epoll_ctl 注册事件并注册 callback 回调函数,epoll_wait 只返回发生的事件避免了像 select 和 poll 对事件的整个轮寻操作。
#include <stdio.h> // for fprintf()
#include <unistd.h> // for close(), read()
#include <sys/epoll.h> // for epoll_create1(), epoll_ctl(), struct epoll_event
#include <string.h> // for strncmp
int main ()
{
int running = 1 , event_count, i;
size_t bytes_read;
char read_buffer [READ_SIZE + 1 ];
struct epoll_event event, events [MAX_EVENTS];
int epoll_fd = epoll_create1 ( 0 );
if (epoll_fd == - 1 ) {
fprintf (stderr, "Failed to create epoll file descriptor \n " );
return 1 ;
}
event.events = EPOLLIN;
event.data.fd = 0 ;
if ( epoll_ctl (epoll_fd, EPOLL_CTL_ADD, 0 , & event))
{
fprintf (stderr, "Failed to add file descriptor to epoll \n " );
close (epoll_fd);
return 1 ;
}
while (running) {
printf ( " \n Polling for input... \n " );
event_count = epoll_wait (epoll_fd, events, MAX_EVENTS, 30000 );
printf ( " %d ready events \n " , event_count);
for (i = 0 ; i < event_count; i ++ ) {
printf ( "Reading file descriptor ' %d ' -- " , events [i].data.fd);
bytes_read = read ( events [i].data.fd, read_buffer, READ_SIZE);
printf ( " %zd bytes read. \n " , bytes_read);
read_buffer [bytes_read] = ' \0 ' ;
printf ( "Read ' %s ' \n " , read_buffer);
if ( ! strncmp (read_buffer, "stop \n " , 5 ))
running = 0 ;
}
}
if ( close (epoll_fd)) {
fprintf (stderr, "Failed to close epoll file descriptor \n " );
return 1 ;
}
return 0 ;
}
Level-triggered and edge-triggered
水平触发 (level-trggered)
只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就一直发出可读信号进行通知,
当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知
边缘触发 (edge-triggered)
当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知,
当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通知
Links