epoll 相关man手册

1.man epoll

arm@arm:~$ man epoll
arm@arm:~$ man epoll
EPOLL(7)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Linux Programmer's Manual                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             EPOLL(7)

NAME
       epoll - I/O event notification facility
       /*I/O 事件通知设施*/

SYNOPSIS
       #include <sys/epoll.h>

DESCRIPTION
       The epoll API performs a similar task to poll(2): monitoring multiple file descriptors to see if I/O is possible on any of them.  
       The epoll API can be used either as an edge-triggered or a level-triggered interface and scales well to large numbers of watched file descriptors.
       /*epoll API执行与poll(2)类似的任务:监视多个文件描述符,以查看其中任何一个文件描述符上是否可以进行I/O。          
       epoll API既可以用作边缘触发接口,也可以用作水平触发接口,并且可以很好地扩展到大量被监视的文件描述符。*/

       The central concept of the epoll API is the epoll instance, an in-kernel data structure which, from a user-space perspective,
        can be considered as a container for two lists:
        /*epoll API的核心概念是epoll实例,这是一个内核内的数据结构,从用户空间的角度来看,可以看作是两个列表的容器:*/

       *   The interest list (sometimes also called the epoll set): the set of file descriptors that the process has registered an interest in monitoring.

       *   The ready list: the set of file descriptors that are "ready" for I/O.  
       The ready list is a subset of (or, more precisely, a set of references to) the file descriptors in the interest list that is dynamically populated 
       by the kernel as a result of I/O activity on those file descriptors.
       /*
       * 兴趣列表(有时也称为epoll集):进程已注册有兴趣监视的文件描述符集。
       * ready list:准备好I/O的文件描述符集合。  
       * 就绪列表是兴趣列表中的文件描述符的子集(或者更准确地说,是一组引用),由内核动态填充,作为这些文件描述符上的I/O活动的结果。
       */


       The following system calls are provided to create and manage an epoll instance:

       *  epoll_create(2) creates a new epoll instance and returns a file descriptor referring to that instance.  
       (The more recent epoll_create1(2) extends the functionality of epoll_create(2).)

       *  Interest in particular file descriptors is then registered via epoll_ctl(2), which adds items to the interest list of the epoll instance.

       *  epoll_wait(2) waits for I/O events, blocking the calling thread if no events are currently available.  
       (This system call can be thought of as fetching items from the ready list of the epoll instance.)

        /*
        以下系统调用用于创建和管理epoll实例:
       *  epoll_create(2)创建一个新的epoll实例,并返回一个引用该实例的文件描述符。 (最近的epoll_create1(2)扩展了epoll_create(2)的功能)。

       *  然后通过epoll_ctl(2)注册对特定文件描述符的兴趣,它将项目添加到epoll实例的兴趣列表中。

       *  epoll_wait(2)等待I/O事件,如果当前没有可用的事件,则阻塞调用线程。 (系统调用可以被认为是从epoll实例的就绪列表中获取项目)。
        */


   Level-triggered and edge-triggered /*水平触发 和边沿触发*/
       The epoll event distribution interface is able to behave both as edge-triggered (ET) and as level-triggered (LT).  
       The difference between the two mechanisms can be described as follows.  Suppose that this scenario happens:
       /*
       epoll事件分发接口能够表现为边沿触发(ET)和电平触发(LT)。          
       这两种机制之间的区别可以描述如下。  
       假设这种情况发生:
       */

       1. The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance.

       2. A pipe writer writes 2 kB of data on the write side of the pipe.

       3. A call to epoll_wait(2) is done that will return rfd as a ready file descriptor.

       4. The pipe reader reads 1 kB of data from rfd.

       5. A call to epoll_wait(2) is done.
       /*
       1. 表示管道读端的文件描述符(rfd)在epoll实例上注册。

       2. 管道写入器在管道的写入端写入2 kB数据。

       3. 调用epoll_wait(2)将返回rfd作为就绪文件描述符。

       4. 管道读取器从rfd读取1 kB数据。

       5. 调用epoll_wait(2)完成。--->可能会产生无限期的阻塞 
       */

       If the rfd file descriptor has been added to the epoll interface using the EPOLLET (edge-triggered) flag, 
       the call to epoll_wait(2) done in step 5 will probably hang despite the available data still present in the file input buffer; 
       meanwhile the remote peer might be expecting a response based on the data it already sent.  
       The reason for this is that edge-triggered mode delivers events only when changes occur on the monitored file descriptor.  
       So, in step 5 the caller might end up waiting for some data that is already present inside the input buffer.  
       In the above example, an event on rfd will be generated because of the write done in 2 and the event is consumed in 3.  
       Since the read operation done in 4 does not consume the whole buffer data, the call to epoll_wait(2) done in step 5 might block indefinitely.
       /*
       如果使用EPOLLET(边缘触发)标志将rfd文件描述符添加到epoll接口,         
       在步骤5中完成的对epoll_wait(2)的调用可能会挂起,尽管文件输入缓冲区中仍然存在可用数据;         
       同时,远程对等端可能期待一个其已经发送的数据的响应。          

       这样做的原因是边缘触发模式仅在被监视的文件描述符发生变化时才传递事件。          

       因此,在步骤5中,调用者可能会等待输入缓冲区中已经存在的某些数据。          

       在上面的示例中,由于在步骤2中完成了写入,将在rfd上生成一个事件,并且该事件在3中使用。          

       由于在步骤4中完成的读取操作不会消耗整个缓冲区数据,所以在步骤5中完成的对epoll_wait(2)的调用可能会无限期地阻塞。
       */

       An application that employs the EPOLLET flag should use nonblocking file descriptors to avoid having a blocking read or write starve a task that is 
       handling multiple file descriptors. 
       The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows:
       /*
       使用EPOLLET标志(边缘触发)的应用程序应该使用非阻塞文件描述符,以避免阻塞读或写使处理多个文件描述符的任务陷入饥饿。         
       使用epoll作为边缘触发(EPOLLET)接口的建议方法如下:
       */


              i   with nonblocking file descriptors; and

              ii  by waiting for an event only after read(2) or write(2) return EAGAIN.
        /*
              i 使用非阻塞文件描述符;以及

              ii 通过仅在read(2)或write(2)之后等待事件返回EAGAIN。
        */

       By contrast, when used as a level-triggered interface (the default, when EPOLLET is not specified), epoll is simply a faster poll(2), 
       and can be used wherever the latter is used since it shares the same semantics.
       /*
       相比之下,当用作级别触发接口时(默认情况下,当未指定EPOLLET时),epoll只是一个更快的轮询(2),        
       并且可以在使用后者的任何地方使用,因为它共享相同的语义。
       */

       Since even with edge-triggered epoll, multiple events can be generated upon receipt of multiple chunks of data, 
       the caller has the option to specify the EPOLLONESHOT flag,
        to tell epoll to disable the associated file descriptor after the receipt of an event with epoll_wait(2).  
        When the EPOLLONESHOT flag is specified, it is the caller's responsibility to rearm the file descriptor using epoll_ctl(2) with EPOLL_CTL_MOD.
        /*
        因为即使使用边缘触发epoll,在接收到多个数据块时也可以生成多个事件,         
        调用者具有指定EPOLLONESHOT标志的选项,         
        告诉epoll在接收到epoll_wait(2)事件后禁用相关的文件描述符。 

        当指定了EPOLLONESHOT标志时,调用者负责使用epoll_ctl(2)和EPOLL_CTL_MOD重新装备文件描述符。
        */

       If multiple threads (or processes, if child processes have inherited the epoll file descriptor across fork(2)) are blocked in epoll_wait(2) 
       waiting on the same epoll file descriptor and a file descriptor in the interest list that is marked for edge-triggered (EPOLLET) notification becomes ready, 
       just one of the threads (or processes) is awoken from epoll_wait(2).  
       This provides a useful optimization for avoiding "thundering herd" wake-ups in some scenarios.
       /*
       如果多个线程(或进程,如果子进程已经跨fork(2)继承了epoll文件描述符)在epoll_wait(2)中被阻塞等待相同的epoll文件描述符
       和兴趣列表中标记为边缘触发(EPOLLET)通知的文件描述符变为就绪,         
       只有一个线程(或进程)从epoll_wait(2)中被唤醒。          
       这提供了一个有用的优化,以避免在某些情况下“雷鸣般的羊群”唤醒。
       */

   Interaction with autosleep /*与autosleep的交互*/
       If the system is in autosleep mode via /sys/power/autosleep and an event happens which wakes the device from sleep, 
       the device driver will keep the device awake only until that event is queued.  
       To keep the device awake until the event has been processed, 
       it is necessary to use the epoll_ctl(2) EPOLLWAKEUP flag.

       /*
       如果系统通过/sys/power/autosleep处于自动休眠模式,并且发生了将设备从休眠状态唤醒的事件,         
       设备驱动程序将保持设备唤醒,直到该事件被排队。          
       为了保持设备唤醒直到事件被处理,         
       必须使用epoll_ctl(2)EPOLLWAKEUP标志。
       */

       When the EPOLLWAKEUP flag is set in the events field for a struct epoll_event, the system will be kept awake from the moment the event is queued, 
       through the epoll_wait(2) call which returns the event until the subsequent epoll_wait(2) call.  
       If the event should keep the system awake beyond that time, then a separate wake_lock should be taken before the second epoll_wait(2) call.
       /*
       当在结构epoll_event的events字段中设置EPOLLWAKEUP标志时,系统将从事件排队的那一刻起保持唤醒,         
       通过epoll_wait(2)调用返回事件,直到随后的epoll_wait(2)调用。          
       如果该事件应该使系统在超过该时间后保持唤醒,则应该在第二次epoll_wait(2)调用之前执行单独的wake_lock。
       */

   /proc interfaces
       The following interfaces can be used to limit the amount of kernel memory consumed by epoll:
       /*可以使用以下接口来限制epoll占用的内核内存量:*/

       /proc/sys/fs/epoll/max_user_watches (since Linux 2.6.28)
              This specifies a limit on the total number of file descriptors that a user can register across all epoll instances on the system.  
              The limit is per real user ID.  Each registered file descriptor costs roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes on a 64-bit kernel.  
              Currently, the default value for max_user_watches is 1/25 (4%) of the available low memory, divided by the registration cost in bytes.
              /*
              这指定了用户可以在系统上的所有epoll实例中注册的文件描述符总数的限制。                 
              每个注册的文件描述符在32位内核上花费大约90个字节,在64位内核上花费大约160个字节。                 
              当前,max_user_watches的默认值是可用低内存的1/25(4%)除以注册成本(字节)。
              */

   Example for suggested usage
       While the usage of epoll when employed as a level-triggered interface does have the same semantics as poll(2), 
       the edge-triggered usage requires more clarification to avoid stalls in the application event loop.  
       In this example, listener is a nonblocking socket on which listen(2) has been called.  
       The function do_use_fd() uses the new ready file descriptor until EAGAIN is returned by either read(2) or write(2). 
        An event-driven state machine application should, after having received EAGAIN, 
        record its current state so that at the next call to do_use_fd() it will continue to read(2) or write(2) from where it stopped before.

        /*
        虽然epoll在用作水平触发接口时的用法确实与poll(2)具有相同的语义,         
        边缘触发的使用需要更多的澄清以避免应用事件循环中的停顿。          
        在这个例子中,监听者是一个非阻塞套接字,在这个套接字上listen(2)被调用。          
        函数do_use_fd()使用新的就绪文件描述符,直到read(2)或write(2)返回EAGAIN。          
        事件驱动的状态机应用程序在接收到EAGAIN之后,          
        记录它的当前状态,以便在下一次调用do_use_fd()时,它将继续从之前停止的位置执行read(2) or write(2)。
        */

           #define MAX_EVENTS 10
           struct epoll_event ev, events[MAX_EVENTS];
           int listen_sock, conn_sock, nfds, epollfd;

           /* Code to set up listening socket, 'listen_sock',
              (socket(), bind(), listen()) omitted */

           epollfd = epoll_create1(0);
           if (epollfd == -1) {
               perror("epoll_create1");
               exit(EXIT_FAILURE);
           }

           ev.events = EPOLLIN;
           ev.data.fd = listen_sock;
           if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
               perror("epoll_ctl: listen_sock");
               exit(EXIT_FAILURE);
           }

           for (;;) {
               nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
               if (nfds == -1) {
                   perror("epoll_wait");
                   exit(EXIT_FAILURE);
               }

               for (n = 0; n < nfds; ++n) {
                   if (events[n].data.fd == listen_sock) {
                       conn_sock = accept(listen_sock,
                                          (struct sockaddr *) &addr, &addrlen);
                       if (conn_sock == -1) {
                           perror("accept");
                           exit(EXIT_FAILURE);
                       }
                       setnonblocking(conn_sock);
                       ev.events = EPOLLIN | EPOLLET;
                       ev.data.fd = conn_sock;
                       if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
                                   &ev) == -1) {
                           perror("epoll_ctl: conn_sock");
                           exit(EXIT_FAILURE);
                       }
                   } else {
                       do_use_fd(events[n].data.fd);
                   }
               }
           }

       When used as an edge-triggered interface, for performance reasons, 
       it is possible to add the file descriptor inside the epoll interface (EPOLL_CTL_ADD) once by specifying (EPOLLIN|EPOLLOUT).  
       This allows you to avoid continuously switching between EPOLLIN and EPOLLOUT calling epoll_ctl(2) with EPOLL_CTL_MOD.
        /*
        当用作边缘触发接口时,出于性能原因,通过指定(EPOLLIN|EPOLLOUT),可以在epoll接口(EPOLL_CTL_ADD)内添加一次文件描述符。          
        这可让您避免在EPOLLIN和EPOLLOUT之间不断切换,并使用EPOLL_CTL_MOD调用epoll_ctl(2)。
        */

   Questions and answers
       0.  What is the key used to distinguish the file descriptors registered in an interest list?

           The key is the combination of the file descriptor number and the open file description
            (also known as an "open file handle", the kernel's internal representation of an open file).

    /*
    0.  用于区分兴趣列表中注册的文件描述符的关键是什么?

        关键是文件描述符号和打开的文件描述的组合(称为“打开文件句柄”,内核对打开文件的内部表示)。
    */            

       1.  What happens if you register the same file descriptor on an epoll instance twice?

           You will probably get EEXIST.  However, it is possible to add a duplicate
            (dup(2), dup2(2), fcntl(2) F_DUPFD) file descriptor to the same epoll instance.  
            This can be a useful technique for filtering events, if the duplicate file descriptors are registered with different events masks.

    /* 
    1.  如果在epoll实例上注册相同的文件描述符两次会发生什么?

           你很可能会得到EEXIST。
           但是,可以添加重复的(dup(2),dup2(2),fcntl(2)F_DUPFD)文件描述符。               
           如果重复的文件描述符使用不同的事件掩码注册,则这对于过滤事件来说是一种有用的技术。
    */

       2.  Can two epoll instances wait for the same file descriptor?  If so, are events reported to both epoll file descriptors?

           Yes, and events would be reported to both.  However, careful programming may be needed to do this correctly.
    /*
    2.  两个epoll实例可以等待相同的文件描述符吗?  如果是,事件是否报告给两个epoll文件描述符?

           是的,事件将向双方报告。  但是,可能需要仔细编程才能正确执行此操作。
    */           

       3.  Is the epoll file descriptor itself poll/epoll/selectable?

           Yes.  If an epoll file descriptor has events waiting, then it will indicate as being readable.
    /*
    3.  epoll文件描述符本身是否为poll/epoll/selectable?

           是的  如果epoll文件描述符有等待的事件,则它将指示为可读。
    */           

       4.  What happens if one attempts to put an epoll file descriptor into its own file descriptor set?

           The epoll_ctl(2) call fails (EINVAL).  However, you can add an epoll file descriptor inside another epoll file descriptor set.
    /*
    4.  如果试图将epoll文件描述符放入自己的文件描述符集中会发生什么?

           epoll_ctl(2)调用失败(EINVAL)。  但是,您可以在另一个epoll文件描述符集中添加epoll文件描述符。
    */           

       5.  Can I send an epoll file descriptor over a UNIX domain socket to another process?

           Yes, but it does not make sense to do this, since the receiving process would not have copies of the file descriptors in the interest list.
    /*
    5.  我可以通过UNIX域套接字向另一个进程发送epoll文件描述符吗?

           是的,但是这样做没有意义,因为接收进程在兴趣列表中没有文件描述符的副本。
    */           

       6.  Will closing a file descriptor cause it to be removed from all epoll interest lists?

           Yes, but be aware of the following point.  A file descriptor is a reference to an open file description (see open(2)). 
            Whenever a file descriptor is duplicated via dup(2), dup2(2), fcntl(2) F_DUPFD, or fork(2),
             a new file descriptor referring to the same open file description is created. 
              An open file description continues to exist until all file descriptors referring to it have been closed.

           A file descriptor is removed from an interest list only after all the file descriptors referring to the underlying open file description have been closed.  
           This means that even after a file descriptor that is part of an interest list has been closed, 
           events may be reported for that file descriptor if other file descriptors referring to the same underlying file description remain open.  
           To prevent this happening, the file descriptor must be explicitly removed from the interest list (using epoll_ctl(2) EPOLL_CTL_DEL) before it is duplicated.  
           Alternatively, the application must ensure that all file descriptors are closed 
           (which may be difficult if file descriptors were duplicated behind the scenes by library functions that used dup(2) or fork(2)).
    /*
    6.  关闭一个文件描述符会导致它从所有epoll兴趣列表中删除吗?

           是的,但要注意以下几点。  
           文件描述符是对打开的文件描述的引用(参见open(2))。              
           每当通过dup(2)、dup2(2)、fcntl(2)F_DUPFD或fork(2)复制文件描述符时,              
           创建引用相同打开文件描述的新文件描述符。                
           打开的文件描述将继续存在,直到所有引用它的文件描述符都被关闭。

           只有在所有引用底层打开文件描述的文件描述符都已关闭后,才能从兴趣列表中删除文件描述符。              
           这意味着即使在作为兴趣列表的一部分的文件描述符被关闭之后,             
           如果引用相同底层文件描述的其它文件描述符保持打开,则可以报告该文件描述符的事件。              
           为了防止这种情况发生,在复制文件描述符之前,必须从兴趣列表中显式删除文件描述符(使用epoll_ctl(2)EPOLL_CTL_DEL)。              
           或者,应用程序必须确保关闭所有文件描述符             
           (如果文件描述符在后台被使用dup(2)或fork(2)的库函数复制,这可能会很困难)。
    */
       7.  If more than one event occurs between epoll_wait(2) calls, are they combined or reported separately?

           They will be combined.
    /*
    7.  如果在epoll_wait(2)调用之间发生了多个事件,它们是合并报告还是单独报告?

           他们将被合并。
    */           

       8.  Does an operation on a file descriptor affect the already collected but not yet reported events?

           You can do two operations on an existing file descriptor.  Remove would be meaningless for this case.  Modify will reread available I/O.
    /*
    8.  对文件描述符的操作是否会影响已收集但尚未报告的事件?

           您可以对现有的文件描述符执行两个操作。  
           删除操作对本案例毫无意义。  
           修改操作将重新读取可用I/O。
    */       

       9.  Do I need to continuously read/write a file descriptor until EAGAIN when using the EPOLLET flag (edge-triggered behavior)?

           Receiving an event from epoll_wait(2) should suggest to you that such file descriptor is ready for the requested I/O operation.  
           You must consider it ready until the next (nonblocking) read/write yields EAGAIN. 
            When and how you will use the file descriptor is entirely up to you.

           For packet/token-oriented files (e.g., datagram socket, terminal in canonical mode), 
           the only way to detect the end of the read/write I/O space is to continue to read/write until EAGAIN.

           For stream-oriented files (e.g., pipe, FIFO, stream socket), 
           the condition that the read/write I/O space is exhausted can also be detected by checking the amount of data read from / written to the target file descriptor.  
           For example, if you call read(2) by asking to read a certain amount of data and read(2) returns a lower number of bytes,
            you can be sure of having exhausted the read I/O space for the file descriptor.  The same is true when writing using write(2).  
            (Avoid this latter technique if you cannot guarantee that the monitored file descriptor always refers to a stream-oriented file.)

    /*
    9.  当使用EPOLLET标志(边缘触发行为)时,我需要连续读/写文件描述符直到EAGAIN吗?

           从epoll_wait(2)接收事件应该向您表明这样的文件描述符已经为请求的I/O操作做好了准备。             
            在下一次(非阻塞)读/写产生EAGAIN之前,您必须将其视为做好了准备。              
            何时以及如何使用文件描述符完全取决于您。

           对于面向分组/令牌的文件(例如, 数据报套接字,规范模式下的终端),             
           检测 读/写 I/O空间结束的唯一方法是继续 读/写 直到EAGAIN。

           对于面向流的文件(例如, 管道、FIFO、流套接字),             
           读/写 I/O空间 耗尽的情况也可以通过检查从目标文件描述符 读取/写入 目标文件描述符的数据量来检测。              
           例如,如果通过请求读取确定量的数据来调用read(2),而read(2)返回较少量的字节数,             
           你可以肯定已经用尽了文件描述符的读I/O空间。  
           当使用write(2)写入时也是如此。               
           (如果不能保证被监视的文件描述符始终引用面向流的文件,请避免使用后一种技术。)
    */

   Possible pitfalls and ways to avoid them 
   /*可能的陷阱和避免它们的方法*/
       o Starvation (edge-triggered)

       If there is a large amount of I/O space, it is possible that by trying to drain it the other files will not get processed causing starvation. 
        (This problem is not specific to epoll.)

       The solution is to maintain a ready list and mark the file descriptor as ready in its associated data structure, 
       thereby allowing the application to remember which files need to be processed but still round robin amongst all the ready files.  
       This also supports ignoring subsequent events you receive for file descriptors that are already ready.

    /*
    饥饿(边缘触发)

       如果有大量的I/O空间,那么通过尝试耗尽它,其他文件可能无法得到处理,从而导致饥饿。   
       (这个问题并不是epoll特有的。)

       解决方案是维护做好了准备的(就绪)列表并在其相关数据结构中将文件描述符标记为就绪,         
       从而允许应用记住哪些文件需要被处理,但仍然在所有准备好的文件中循环。          
       这也支持忽略您收到的已经准备好的文件描述符的后续事件。
    */

       o If using an event cache...

       If you use an event cache or store all the file descriptors returned from epoll_wait(2), 
       then make sure to provide a way to mark its closure dynamically (i.e., caused by a previous event's processing).  
       Suppose you receive 100 events from epoll_wait(2), and in event #47 a condition causes event #13 to be closed.  
       If you remove the structure and close(2) the file descriptor for event #13, 
       then your event cache might still say there are events waiting for that file descriptor causing confusion.

       One solution for this is to call, 
       during the processing of event 47, epoll_ctl(EPOLL_CTL_DEL) to delete file descriptor 13 and close(2), 
       then mark its associated data structure as removed and link it to a cleanup list.  
       If you find another event for file descriptor 13 in your batch processing, 
       you will discover the file descriptor had been previously removed and there will be no confusion.

    /*
    o如果使用事件缓存.

       如果从epoll_wait(2)返回的所有文件描述符使用事件缓存或存储,         
       则确保提供了一种动态地标记其关闭的方式(即,由先前事件的处理引起)。          
       假设从epoll_wait(2)接收到100个事件,在事件#47中,一个条件导致事件#13关闭。         
       如果你删除结构并close(2)事件#13的文件描述符,         
       那么你的事件缓存可能仍然会说有事件在等待那个文件描述符,从而导致混乱。

       一个解决办法是调用,        
        在事件47的处理期间,epoll_ctl(EPOLL_CTL_DEL)删除文件描述符13并close(2),         
        然后将其关联的数据结构标记为已删除,并将其关联到清除列表。          
        如果在批处理中发现文件描述符13的另一个事件,         
        你会发现文件描述符已经被删除,不会有任何混乱。
    */   

VERSIONS
       The epoll API was introduced in Linux kernel 2.5.44.  Support was added to glibc in version 2.3.2.

CONFORMING TO
       The epoll API is Linux-specific.  Some other systems provide similar mechanisms, for example, FreeBSD has kqueue, and Solaris has /dev/poll.

NOTES
       The set of file descriptors that is being monitored via an epoll file descriptor 
       can be viewed via the entry for the epoll file descriptor in the process's /proc/[pid]/fdinfo directory.  
       See proc(5) for further details.

       The kcmp(2) KCMP_EPOLL_TFD operation can be used to test whether a file descriptor is present in an epoll instance.

SEE ALSO
       epoll_create(2), epoll_create1(2), epoll_ctl(2), epoll_wait(2), poll(2), select(2)

COLOPHON
       This page is part of release 5.05 of the Linux man-pages project.  
       A description of the project, information about reporting bugs, and the latest version of this page, can be found at https://www.kernel.org/doc/man-pages/.

Linux                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        2019-03-06                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     EPOLL(7)
~
~

 2.epoll_ctl - control interface for an epoll file descriptor

/*epoll_ctl -epoll文件描述符的控制接口*/

EPOLL_CTL(2)                                                                          Linux Programmer's Manual                                                                          EPOLL_CTL(2)

NAME
       epoll_ctl - control interface for an epoll file descriptor
       /*epoll_ctl -epoll文件描述符的控制接口*/

SYNOPSIS
       #include <sys/epoll.h>

       int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

DESCRIPTION
       This  system  call is used to add, modify, or remove entries in the interest list of the epoll(7) instance referred to by the file descriptor epfd.  
       It requests that the operation op be per‐formed for the target file descriptor, fd.
       /*
       这个系统调用用于在epoll(7)实例的兴趣列表中添加、修改或删除由文件描述符epfd引用的条目。          
       它请求对目标文件描述符fd执行操作op。
       */

       /*op参数可用的值如下*/
       Valid values for the op argument are: 

       EPOLL_CTL_ADD
              Add fd to the interest list and associate the settings specified in event with the internal file linked to fd.
              /*将fd添加到兴趣列表中,并将事件中指定的设置与链接到fd的内部文件相关联。*/

       EPOLL_CTL_MOD
              Change the settings associated with fd in the interest list to the new settings specified in event.
              /*将兴趣列表中与fd关联的设置更改为事件中指定的新设置。*/

       EPOLL_CTL_DEL
              Remove (deregister) the target file descriptor fd from the interest list.  The event argument is ignored and can be NULL (but see BUGS below).
              /*从兴趣列表中删除(注销)目标文件描述符fd。  事件参数被忽略,可以为NULL(但请参阅下面的BUGS)。*/

       The event argument describes the object linked to the file descriptor fd.  The struct epoll_event is defined as:
       /*事件参数描述链接到文件描述符fd的对象。 结构epoll_event定义为:*/

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

       The events member is a bit mask composed by ORing together zero or more of the following available event types:
       /*events成员是一个位掩码,由以下可用事件类型中的零个或多个组成:*/

       EPOLLIN
              The associated file is available for read(2) operations.
              /*关联的文件可用于read(2)操作。*/

       EPOLLOUT
              The associated file is available for write(2) operations.
              /*关联的文件可用于write(2)操作。*/

       EPOLLRDHUP (since Linux 2.6.17)
              Stream socket peer closed connection, or shut down writing half of connection.
                (This flag is especially useful for writing simple code to detect peer shutdown when using  Edge Triggered monitoring.)
              /*
               流套接字对等端关闭连接,或关闭写的半连接。
                (此标志对于编写简单的代码以在使用边沿触发监视时检测对等端是否设备关闭特别有用。
              */  

       EPOLLPRI
              There is an exceptional condition on the file descriptor.  See the discussion of POLLPRI in poll(2).
              /*文件描述符上存在异常情况。 参见poll(2)中对POLLPRI的讨论。*/

       EPOLLERR
              Error  condition happened on the associated file descriptor.  
              This event is also reported for the write end of a pipe when the read end has been closed.  
              epoll_wait(2) will always re‐port for this event; it is not necessary to set it in events.
              /*
              相关文件描述符发生错误。                 
              当读端关闭时,也会为管道的写端报告此事件。                 
              epoll_wait(2)将始终报告此事件;没有必要在events中设置它。
              */

       EPOLLHUP
              Hang up happened on the associated file descriptor.  epoll_wait(2) will always wait for this event; it is not necessary to set it in events.

              Note that when reading from a channel such as a pipe or a stream socket, this event merely indicates that the peer closed its end of the channel.  
              Subsequent reads  from  the  channel will return 0 (end of file) only after all outstanding data in the channel has been consumed.
              /*
              关联的文件描述符发生挂起。  
              epoll_wait(2)将始终等待此事件;没有必要在events中设置它。

              请注意,当从通道(如管道或流套接字)进行读时,此事件仅表示对等方关闭了通道的一端。                 
              只有在通道中所有未完成的数据都被使用后,从通道进行的后续读取才会返回0(文件结束)。
              */


       EPOLLET
              Sets  the  Edge  Triggered  behavior for the associated file descriptor.  
              The default behavior for epoll is Level Triggered.  
              See epoll(7) for more detailed information about Edge and Level Triggered event distribution architectures.
              /*
              为关联的文件描述符设置边缘触发行为。                 
              epoll的默认行为是Level Triggered。                 
              请参阅epoll(7)以了解有关边缘和级别触发事件分发架构的更多详细信息。
              */

       EPOLLONESHOT (since Linux 2.6.2)
              Sets the one-shot behavior for the associated file descriptor.  
              This means that after an event is pulled out with epoll_wait(2) the associated file descriptor is  internally  disabled
              and no other events will be reported by the epoll interface.  
              The user must call epoll_ctl() with EPOLL_CTL_MOD to rearm the file descriptor with a new event mask.
              /*
              设置关联文件描述符的一次性行为。                 
              这意味着在使用epoll_wait(2)取出事件后,相关的文件描述符将在内部被禁用并且EPoll接口将不报告其它事件。                 
              用户必须使用EPOLL_CTL_MOD调用epoll_ctl(),以使用新的事件掩码重新武装文件描述符。
              */

       EPOLLWAKEUP (since Linux 3.5)
              If  EPOLLONESHOT and EPOLLET are clear and the process has the CAP_BLOCK_SUSPEND capability, 
              ensure that the system does not enter "suspend" or "hibernate" while this event is pending or being processed.  
              The event is considered as being "processed" from the time when it is returned by a call to epoll_wait(2) until  the  next  call  to  
              epoll_wait(2)  on  the  same  epoll(7)  file descriptor, the closure of that file descriptor,
              the removal of the event file descriptor with EPOLL_CTL_DEL, or the clearing of EPOLLWAKEUP for the event file descriptor with EPOLL_CTL_MOD.  
              See also BUGS.
              /*
              如果EPOLLONESHOT和EPOLLET已清除,并且进程具有CAP_BLOCK_SUSPEND功能,                
              确保在此事件挂起或正在处理时,系统不会进入“挂起”或“休眠”状态。                 

              该事件被考虑“处理”,从调用epoll_wait(2)返回事件时起,
              直到在同一epoll(7)文件描述符下一次调用epoll_wait(2),
              关闭该文件描述符,               
              使用EPOLL_CTL_DEL删除事件文件描述符,或使用EPOLL_CTL_MOD清除事件文件描述符的EPOLLWAKEUP。                 
              参考BUGS。
              */

       EPOLLEXCLUSIVE (since Linux 4.5)  //独占唤醒模式 
              Sets an exclusive wakeup mode for the epoll file descriptor that is being attached to the target file descriptor, fd.  
              When a wakeup event occurs and multiple epoll  file  descriptors are  attached  to  the  same  target file using EPOLLEXCLUSIVE, 
              one or more of the epoll file descriptors will receive an event with epoll_wait(2).  
              The default in this scenario (when EPOLLEXCLUSIVE is not set) is for all epoll file descriptors to receive an event.  
              EPOLLEXCLUSIVE is thus useful for avoiding thundering herd problems in certain scenarios.
              /*
              为附加到目标文件描述符fd的epoll文件描述符设置独占唤醒模式。                 
              当唤醒事件发生并且多个epoll文件描述符使用EPOLLEXCLUSIVE附加到同一个目标文件时,                
              一个或多个epoll文件描述符将接收具有epoll_wait(2)的事件。                
              在这种情况下(当EPOLLEXCLUSIVE未设置时),默认情况是所有epoll文件描述符都接收一个事件。                 
              因此,EPOLLEXCLUSIVE在某些情况下有助于避免雷鸣般的羊群问题。
              */

              If the same file descriptor is in multiple epoll instances, some with the EPOLLEXCLUSIVE flag, 
              and others without, 
              then events will be provided to all epoll  instances  that  did  not specify EPOLLEXCLUSIVE, 
              and at least one of the epoll instances that did specify EPOLLEXCLUSIVE.
              /*
              如果同一个文件描述符存在于多个epoll实例中,其中一些实例带有EPOLLEXCLUSIVE标志,                
              而其他人没有,                
              则事件将被提供给没有指定EPOLLEXCLUSIVE的所有epoll实例,                
              以及至少一个指定了EPOLLEXCLUSIVE的epoll实例。
              */

              The  following  values  may be specified in conjunction with EPOLLEXCLUSIVE: EPOLLIN, EPOLLOUT, EPOLLWAKEUP, and EPOLLET.  
              EPOLLHUP and EPOLLERR can also be specified, 
              but this is not required: as usual, these events are always reported if they occur,
              regardless of whether they are specified in events.  
              Attempts to specify other values in  events  yield  the  error EINVAL.
              /*
              以下值可以与EPOLLEXCLUSIVE一起指定:EPOLLIN、EPOLLOUT、EPOLLWAKEUP和EPOLLET。                 
              也可以指定EPOLLHUP和EPOLLER,                
              但这不是必需的:通常,如果这些事件发生,则总是报告它们,               
              而不管它们是否在事件中指定。                 
              尝试在事件中指定其他值会产生错误EINVAL。
              */

              EPOLLEXCLUSIVE  may be used only in an EPOLL_CTL_ADD operation; 
              attempts to employ it with EPOLL_CTL_MOD yield an error.  
              If EPOLLEXCLUSIVE has been set using epoll_ctl(), then a sub‐sequent EPOLL_CTL_MOD on the same epfd, fd pair yields an error.  
              A call to epoll_ctl() that specifies EPOLLEXCLUSIVE in events and specifies the target file descriptor fd as an epoll
              instance will likewise fail.  
              The error in all of these cases is EINVAL.
              /*
              EPOLLEXCLUSIVE只能在EPOLL_CTL_ADD操作中使用;                
              尝试将其与EPOLL_CTL_MOD一起使用会产生错误。                 
              如果使用epoll_ctl()设置了EPOLLEXCLUSIVE,则同一epfd,fd对上的子表EPOLL_CTL_MOD将产生错误。                 
              调用epoll_ctl(),在事件中指定EPOLLEXCLUSIVE,并将目标文件描述符fd指定为epoll同样会失败。                 
              所有这些情况下的错误都是EINVAL。
              */

RETURN VALUE
       When successful, epoll_ctl() returns zero.  When an error occurs, epoll_ctl() returns -1 and errno is set appropriately.
       /*如果成功,epoll_ctl()返回零。  当发生错误时,epoll_ctl()返回-1,并适当地设置errno。*/

ERRORS
       EBADF  epfd or fd is not a valid file descriptor. //epfd 或者 fd 不是一个可用的文件描述符

       EEXIST op was EPOLL_CTL_ADD, and the supplied file descriptor fd is already registered with this epoll instance.
       //op是EPOLL_CTL_ADD,并且提供的文件描述符fd已经注册到此epoll实例。

       EINVAL epfd is not an epoll file descriptor, or fd is the same as epfd, or the requested operation op is not supported by this interface.
       //epfd不是epoll文件描述符,或者fd与epfd相同,或者此接口不支持请求的操作op。

       EINVAL An invalid event type was specified along with EPOLLEXCLUSIVE in events.
       // 事件中的伴随着EPOLLEXCLUSIVE指定了无效的事件类型。

       EINVAL op was EPOLL_CTL_MOD and events included EPOLLEXCLUSIVE.
       // op为EPOLL_CTL_MOD,事件包括EPOLLEXCLUSIVE。

       EINVAL op was EPOLL_CTL_MOD and the EPOLLEXCLUSIVE flag has previously been applied to this epfd, fd pair.
       // op为EPOLL_CTL_MOD,EPOLLEXCLUSIVE标志先前已应用于此epfd,fd配对。

       EINVAL EPOLLEXCLUSIVE was specified in event and fd refers to an epoll instance.
       // 在event中指定了EPOLLEXCLUSIVE,fd引用epoll实例。

       ELOOP  fd refers to an epoll instance and this EPOLL_CTL_ADD operation would result in a circular loop of epoll instances monitoring one another.
       // fd引用epoll实例,此EPOLL_CTL_ADD操作将导致epoll实例相互监视的循环。

       ENOENT op was EPOLL_CTL_MOD or EPOLL_CTL_DEL, and fd is not registered with this epoll instance.
       // ENOENT操作为EPOLL_CTL_MOD或EPOLL_CTL_DEL,并且fd未注册到此epoll实例。

       ENOMEM There was insufficient memory to handle the requested op control operation.
       // 没有足够的内存去处理op控制操作请求 

       ENOSPC The limit imposed by /proc/sys/fs/epoll/max_user_watches was encountered while trying to register (EPOLL_CTL_ADD) a new file descriptor on an epoll instance.  
       See epoll(7) for further  details.
       // ENOSPC尝试在epoll实例上注册(EPOLL_CTL_ADD)新文件描述符时遇到/proc/sys/fs/epoll/max_user_watches所施加的限制。          
       //请参阅epoll(7)了解更多细节。


       EPERM  The target file fd does not support epoll.  This error can occur if fd refers to, for example, a regular file or a directory.
       // EPERM目标文件fd不支持epoll。  例如,如果fd引用常规文件或目录,则可能发生此错误。

VERSIONS
       epoll_ctl() was added to the kernel in version 2.6.

CONFORMING TO
       epoll_ctl() is Linux-specific.  Library support is provided in glibc starting with version 2.3.2.

NOTES
       The epoll interface supports all file descriptors that support poll(2).
       // epoll接口支持所有支持poll(2)的文件描述符。

BUGS
       In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required a non-null pointer in event, even though this argument is ignored.  
       Since Linux 2.6.9, event can be  specified  as  NULL when using EPOLL_CTL_DEL. 
       Applications that need to be portable to kernels before 2.6.9 should specify a non-null pointer in event.
       /*
       在2.6.9之前的内核版本中,EPOLL_CTL_DEL操作在事件中需要一个非空指针,即使该参数被忽略。          
       从Linux 2.6.9开始,使用EPOLL_CTL_DEL时可以将事件指定为NULL。         
       需要移植到2.6.9之前的内核的应用程序应该在事件中指定一个非空指针。
       */

       If  EPOLLWAKEUP  is  specified in flags, but the caller does not have the CAP_BLOCK_SUSPEND capability, 
       then the EPOLLWAKEUP flag is silently ignored. 
       /*如果在标志中指定了EPOLLWAKEUP,但调用方没有CAP_BLOCK_SUSPEND功能,则EPOLLWAKEUP标志被静默地忽略。*/

       This unfortunate behavior is necessary because no validity checks were performed on the flags argument in the original implementation, 
       and the addition of the EPOLLWAKEUP with a check that caused the call to fail  if  the  caller
       did not have the CAP_BLOCK_SUSPEND capability caused a breakage in at least one existing user-space application that
        happened to randomly (and uselessly) specify this bit.  
       /*
       这种不幸的行为是必要的,因为在原始实现中没有对flags参数执行有效性检查,         
       以及添加EPOLLWAKEUP,如果调用者没有CAP_BLOCK_SUSPEND功能,
       导致至少一个现有的用户空间应用程序中断,该应用程序碰巧随机(且无用)指定了此位。
       */
       
       A robust applica‐tion should therefore double check that it has the CAP_BLOCK_SUSPEND capability if attempting to use the EPOLLWAKEUP flag.
       //因此,健壮的应用程序在尝试使用EPOLLWAKEUP标志时应仔细检查是否具有CAP_BLOCK_SUSPEND功能。

SEE ALSO
       epoll_create(2), epoll_wait(2), poll(2), epoll(7)

COLOPHON
       This page is part of release 5.05 of the Linux man-pages project.  
       A description of the project, information about reporting bugs, and the latest version  of  this  page,  can  be  found  at
       https://www.kernel.org/doc/man-pages/.

Linux                                                                                         2019-03-06                                                                                 EPOLL_CTL(2)

3.epoll_create 

EPOLL_CREATE(2)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Linux Programmer's Manual                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      EPOLL_CREATE(2)

NAME
       epoll_create, epoll_create1 - open an epoll file descriptor

SYNOPSIS
       #include <sys/epoll.h>

       int epoll_create(int size);
       int epoll_create1(int flags);

DESCRIPTION
       epoll_create() creates a new epoll(7) instance.  Since Linux 2.6.8, the size argument is ignored, but must be greater than zero; see NOTES below.
        /*epoll_create()创建一个新的epoll(7)实例。  从Linux 2.6.8开始,size参数被忽略,但必须大于零;请参阅下面的注释。*/

       epoll_create() returns a file descriptor referring to the new epoll instance.  
       This file descriptor is used for all the subsequent calls to the epoll interface.  
       When no longer required, the file descriptor returned by epoll_create() should be closed by using close(2).  
       When all file descriptors referring to an epoll instance have been closed, the kernel destroys the instance and releases the associated resources for reuse.
       /*
       epoll_create()返回指向新epoll实例的文件描述符。          
       这个文件描述符用于所有对epoll接口的后续调用。          
       当不再需要时,epoll_create()返回的文件描述符应该使用close(2)关闭。          
       当所有引用epoll实例的文件描述符都被关闭时,内核会销毁该实例并释放相关资源以供重用。
       */

   epoll_create1()
       If flags is 0, then, other than the fact that the obsolete size argument is dropped, epoll_create1() is the same as epoll_create(). 
        The following value can be included in flags to obtain different behavior:
        /*
        如果flags为0,那么除了删除过时的size参数之外,epoll_create1()与epoll_create()相同。          
        以下值可以包含在标志中以获得不同的行为:
        */

       EPOLL_CLOEXEC
              Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor.  
              See the description of the O_CLOEXEC flag in open(2) for reasons why this may be useful.
              /*
              在新文件描述符上设置执行时关闭(FD_CLOEXEC)标志。                 
              请参阅open(2)中对O_CLOEXEC标志的描述,了解其有用的原因。
              */

       ////////////////////////////////////////////////////////////////////////

       O_CLOEXEC (since Linux 2.6.23)
              Enable  the  close-on-exec  flag for the new file descriptor. 
               Specifying this flag permits a program to avoid additional fcntl(2) F_SETFD operations to set the FD_CLOEXEC flag.

              Note that the use of this flag is essential in some multithreaded programs, because using a separate fcntl(2) F_SETFD operation to set the
              FD_CLOEXEC  flag  does not suffice to avoid race conditions where one thread opens a file descriptor and attempts to set its close-on-exec
              flag using fcntl(2) at the same time as another thread does a fork(2) plus execve(2).  
              
              Depending on the order of execution, 
              the  race  may lead  to  the  file  descriptor  returned  by  
              open() being unintentionally leaked to the program executed by the child process created by fork(2). 
               (This kind of race is in principle possible for any system call that creates a file descriptor whose close-on-exec  flag  should
              be set, and various other Linux system calls provide an equivalent of the O_CLOEXEC flag to deal with this problem.)
       ============
       O_CLOEXEC(自Linux 2.6.23起)               
       为新文件描述符启用close-on-exec标志。  
       声明此标志来允许程序避免额外的fcntl(2)F_SETFD操作来设置FD_CLOEXEC标志。

       请注意,在某些多线程程序中,使用此标志是必不可少的,
       因为使用单独的fcntl(2)F_SETFD操作来设置 FD_CLOEXEC标志
       不足以避免竞争条件:
       一个线程打开文件描述符,并试图使用fcntl(2)设置其close-on-exec 标记时,
       同时另一个线程可能是fork(2)和execve(2)来设置此标志。  

       根据执行的顺序,竞争可能导致open()返回的文件描述符被无意中泄露给由fork(2)创建的子线程。

        这种类型的竞争原则上都可能存在一种竞争,对于创建文件描述符的任何系统调用,其他各种Linux系统调用都提供了一个O_CLOEXEC标志的等价物来处理这个问题。)
       ////////////////////////////////////////////////////////////////////////


RETURN VALUE
       On success, these system calls return a nonnegative file descriptor.  On error, -1 is returned, and errno is set to indicate the error.
      /*
      返回成功,则这个系统调用返回非负数的文件描述符;
      返回错误,返回-1,并且errno被设置,指示错误
      */
ERRORS
       EINVAL size is not positive.  /*EINVAL大小不是正数。*/

       EINVAL (epoll_create1()) Invalid value specified in flags. /*EINVAL(epoll_create1())标志中指定的值无效。*/

       EMFILE The per-user limit on the number of epoll instances imposed by /proc/sys/fs/epoll/max_user_instances was encountered.  See epoll(7) for further details.
       /*EMFILE遇到了 对端用户受到了epoll实例数 /proc/sys/fs/epoll/max_user_instances的限制。 请参阅epoll(7)了解更多细节。*/
       
       /* arm@arm:/proc/sys/fs/epoll$ cat max_user_watches 
          1789395
       */

       EMFILE The per-process limit on the number of open file descriptors has been reached.
       /*EMFILE已达到每个进程打开的文件描述符的数量限制。*/

       ENFILE The system-wide limit on the total number of open files has been reached.
       /*ENFILE已达到系统范围内打开文件总数的限制。*/

       ENOMEM There was insufficient memory to create the kernel object.
       /*ENOMEM内存不足,无法创建内核对象。*/

VERSIONS
       epoll_create() was added to the kernel in version 2.6.  Library support is provided in glibc starting with version 2.3.2.

       epoll_create1() was added to the kernel in version 2.6.27.  Library support is provided in glibc starting with version 2.9.

CONFORMING TO
       epoll_create() is Linux-specific.

NOTES
       In the initial epoll_create() implementation, 
       the size argument informed the kernel of the number of file descriptors that the caller expected to add to the epoll instance.  
       The kernel used this information as a hint for the amount of space to initially allocate in internal data structures describing events. 
        (If necessary, the kernel would allocate more space if the caller's usage exceeded the hint given in size.)  
        Nowadays, this hint is no longer required (the kernel dynamically sizes the required data structures without needing the hint), 
        but size must still be greater than zero, in order to ensure backward compatibility when new epoll applications are run on older kernels.
        /*
        在最初的epoll_create()实现中,        
        size参数通知内核调用者期望添加到epoll实例的文件描述符的数量。          
        内核将此信息用作在描述事件的内部数据结构中初始分配的空间量的提示。          
        (如果调用者的使用量超过了大小中给出的提示,内核将分配更多的空间。)           
        现在,不再需要这个提示(内核动态调整所需的数据结构而不需要提示),          
        但是size仍然必须大于零,以便确保当新的epoll应用程序在旧的内核上运行时的向后兼容性。
        */

SEE ALSO
       close(2), epoll_ctl(2), epoll_wait(2), epoll(7)

COLOPHON
       This page is part of release 5.05 of the Linux man-pages project.  
       A description of the project, information about reporting bugs, and the latest version of this page, can be found at https://www.kernel.org/doc/man-pages/.

Linux                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        2017-09-15                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              EPOLL_CREATE(2)
~
~
~

 4. epoll_wait-man

EPOLL_WAIT(2)              Linux Programmer's Manual             EPOLL_WAIT(2)

NAME
       epoll_wait,  epoll_pwait  -  wait for an I/O event on an epoll file descriptor
       /*等待epoll文件描述符上的I/O事件*/

SYNOPSIS
       #include <sys/epoll.h>

       int epoll_wait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout);
       int epoll_pwait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout,
                      const sigset_t *sigmask);

DESCRIPTION
       The epoll_wait() system call waits for events on the epoll(7)  instance
       referred to by the file descriptor epfd.  The memory area pointed to by
       events will contain the events that will be available for  the  caller.
       Up  to  maxevents are returned by epoll_wait().  The maxevents argument
       must be greater than zero.
       /*
       epoll_wait()这个系统调用,用于等待epoll(7)实例的文件描述符epfd引用的事件。 
       events所指向的内存区域将包含可用于调用者的事件。
       epoll_wait()返回最大maxevents。  
       maxevents参数必须大于零。
       */

       The  timeout  argument  specifies  the  number  of  milliseconds   that
       epoll_wait()  will block.  Time is measured against the CLOCK_MONOTONIC
       clock.  The call will block until either:
       /*
       timeout参数指定epoll_wait()将阻塞的毫秒数。  
       时间是根据CLOCK_MONOTONIC测量的时钟,
       调用将被阻止直到下面的情况:
       */

       *  a file descriptor delivers an event;

       *  the call is interrupted by a signal handler; or

       *  the timeout expires.

       /*
       *  文件描述符传递某个事件;

       *  调用被某个信号处理程序中断;或

       *  超时。
       */

       Note that the timeout interval will be rounded up to the  system  clock granularity, 
       and kernel scheduling delays mean that the blocking interval may overrun by a small amount.  
       Specifying a timeout of  -1  causes epoll_wait() to block indefinitely, 
       while specifying a timeout equal to zero cause epoll_wait() to return immediately, 
       even if  no  events  are available.
       /*
       请注意,超时间隔将四舍五入到系统时钟粒度,内核调度延时意味着阻塞间隔时间可能会溢出一小部分。          
       如果超时时间为-1,则epoll_wait()将无限期阻塞,如果超时时间为0,则epoll_wait()将立即返回,        
       即使没有事件可用。
       */

       /*epoll_event结构体定义如下:*/
       The struct epoll_event is defined as:

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

       The data field of each returned structure contains the same data as was specified in the  most  recent  call  to  epoll_ctl(2)  
       (EPOLL_CTL_ADD,EPOLL_CTL_MOD) for the corresponding open file description.  
       The events field contains the returned event bit field.
       /*
       每个返回的结构中的数据data字段,
       包含的数据
       与最近一次调用epoll_ctl(2)时(EPOLL_CTL_ADD,EPOLL_CTL_MOD)获取相应的已经打开文件的描述符 
       的指定的数据相同。          
       events字段包含返回的事件位bit字段。
       */

   epoll_pwait()
       The relationship between epoll_wait() and epoll_pwait() is analogous to
       the  relationship  between  select(2)  and pselect(2): like pselect(2),
       epoll_pwait() allows an application to safely wait until either a  file
       descriptor becomes ready or until a signal is caught.
       /*
       epoll_wait()和epoll_pwait()之间的关系类似于select(2)和pselect(2)之间的关系:与pselect(2)类似,        
       epoll_pwait()允许应用程序安全地等待,直到文件描述符准备就绪或直到捕获信号。
       */

       /*下面是epoll_pwait的调用:*/
       The following epoll_pwait() call:

           ready = epoll_pwait(epfd, &events, maxevents, timeout, &sigmask);

       /*相当于原子地执行以下调用*/
       is equivalent to atomically executing the following calls:

           sigset_t origmask;

           pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
           ready = epoll_wait(epfd, &events, maxevents, timeout);
           // examine and change mask of blocked signals 检查和改变阻塞信号的mask掩码 
           pthread_sigmask(SIG_SETMASK, &origmask, NULL);

       /*
        sigmask参数可以指定为NULL,在这种情况下epoll_pwait()等同于epoll_wait()。
       */
       The   sigmask  argument  may  be  specified  as  NULL,  
       in  which  case epoll_pwait() is equivalent to epoll_wait().

RETURN VALUE
       When successful, epoll_wait() returns the number  of  file  descriptors ready for the requested I/O,
        or zero if no file descriptor became ready during the requested  timeout  milliseconds.   
       When  an  error  occurs, epoll_wait() returns -1 and errno is set appropriately.
       /*
       成功时,epoll_wait()返回为请求的I/O准备好的文件描述符的数量,         
       或者如果在请求的超时毫秒期间没有文件描述符变为就绪,则为零。
       当发生错误时,epoll_wait()返回-1,并适当地设置errno。
       */

ERRORS
       EBADF  epfd is not a valid file descriptor.
       // EBADF epfd不是有效的文件描述符。

       EFAULT The  memory  area  pointed  to  by events is not accessible with write permissions.
       // 事件所指向的内存区域无法使用写权限访问。

       EINTR  The call was interrupted by a signal handler before  either  (1) any of the requested events occurred or (2) the timeout expired;
              see signal(7).
       // 调用被信号处理程序中断:(1)任何请求的事件发生之前或(2)超时过期之前; 参见信号(7)。       

       EINVAL epfd is not an epoll file descriptor, or maxevents is less  than or equal to zero.
       // epfd不是epoll文件描述符,或者maxevents小于或等于零。

VERSIONS
       epoll_wait()  was  added to the kernel in version 2.6.  Library support
       is provided in glibc starting with version 2.3.2.

       epoll_pwait() was added to Linux in kernel 2.6.19.  Library support  is
       provided in glibc starting with version 2.6.

CONFORMING TO
       epoll_wait() is Linux-specific.

NOTES
       While  one  thread is blocked in a call to epoll_wait(), it is possible for another thread to add a file descriptor to  the  waited-upon  epoll instance.   
       If the new file descriptor becomes ready, it will cause the epoll_wait() call to unblock.
       /* 
       当一个线程在调用epoll_wait()时被阻塞时,另一个线程可以向等待的epoll实例添加文件描述符。           
       如果新的文件描述符准备就绪,它将导致epoll_wait()调用解除阻塞。
       */

       If more than maxevents file descriptors are ready when epoll_wait()  is called, 
       then successive epoll_wait() calls will round robin through the set of ready file descriptors.  
       This behavior  helps  avoid  starvation scenarios,  
       where  a  process  fails to notice that additional file descriptors are ready because it focuses on a  set  of  file  descriptors that are already known to be ready.
       /*
       如果调用epoll_wait()时有超过maxevents的文件描述符准备就绪, 则连续的epoll_wait()调用将循环通过就绪文件描述符的集合。          
       这种行为有助于避免饥饿情况,其中进程未能注意到附加文件描述符已就绪,因为它关注于已知已就绪的一组文件描述符。
       */

       Note  that  it  is  possible  to call epoll_wait() on an epoll instance whose interest list is currently empty
        (or whose interest list  becomes empty  because file descriptors are closed or removed from the interest in another thread).  
       The call will block until some file descriptor  is later  added to the interest list (in another thread) and that file descriptor becomes ready.
       /*
       注意,可以在兴趣列表当前为空的epoll实例上调用epoll_wait()(或者由于文件描述符被关闭或从另一个线程的兴趣中删除而使兴趣列表变为空)。          
       这个调用将阻塞,直到某个文件描述符后来被添加到兴趣列表(在另一个线程中),并且该文件描述符准备就绪。
       */

BUGS
       In kernels before 2.6.37, a timeout  value  larger  than  approximately LONG_MAX  /  HZ  milliseconds is treated as -1 (i.e., infinity).  
       Thus,for example, on a system where sizeof(long) is  4  and  the  kernel  HZ value  is 1000, 
       this means that timeouts greater than 35.79 minutes are treated as infinity.
       /*
       在2.6.37之前的内核中,大于大约LONG_MAX / HZ毫秒的超时值被视为-1(即, 无穷大)。          
       因此,例如,在sizeof(long)为4且内核HZ值为1000的系统上,这意味着大于35.79分钟的超时被视为无穷大。
       */

   C library/kernel differences
       The raw epoll_pwait() system call has a sixth argument, size_t  sigset‐size,  which  specifies the size in bytes of the sigmask argument.  
       The glibc epoll_pwait() wrapper function specifies this argument as a fixed value (equal to sizeof(sigset_t)).
       /*
       原始epoll_pwait()系统调用有第六个参数size_t sigset‐size,它指定sigmask参数的字节大小。          
       glibc epoll_pwait()包装器函数将此参数指定为固定值(等于sizeof(sigset_t))。
       */

SEE ALSO
       epoll_create(2), epoll_ctl(2), epoll(7)

COLOPHON
       This  page  is  part of release 5.05 of the Linux man-pages project.  A
       description of the project, information about reporting bugs,  and  the
       latest     version     of     this    page,    can    be    found    at
       https://www.kernel.org/doc/man-pages/.

Linux                             2019-03-06                     EPOLL_WAIT(2)

 

posted @ 2024-01-06 10:26  OzTaking  阅读(68)  评论(0编辑  收藏  举报