Linux面試必知: 一句話講透epoll

Linux面試必知: 一句話講透epoll
epoll概念

在Linux的Man文檔中,我們可以看到如下定義

    Epoll - I/O event notification facility

翻譯一下,epoll是一種I/O事件通知機制,這句話基本上包含了所有需要理解的要點

    I/O事件
        基於file descriptor,支持file, socket, pipe等各種I/O方式
        當文件描述符關聯的內核讀緩衝區可讀,則觸發可讀事件,什麼是可讀呢?就是內核緩衝區非空,有數據可以讀取
        當文件描述符關聯的內核寫緩衝區可寫,則觸發可寫事件,什麼是可寫呢?就是內核緩衝區不滿,有空閒空間可以寫入
    通知機制
        通知機制,就是當事件發生的時候,去通知他
        通知機制的反面,就是輪詢機制

以上兩點結合起來理解

    epoll是一種當文件描述符的內核緩衝區非空的時候,發出可讀信號進行通知,當寫緩衝區不滿的時候,發出可寫信號通知的機制

水平觸發與邊緣觸發

    水平觸發(level-trggered)
        只要文件描述符關聯的讀內核緩衝區非空,有數據可以讀取,就一直髮出可讀信號進行通知,
        當文件描述符關聯的內核寫緩衝區不滿,有空間可以寫入,就一直髮出可寫信號進行通知
    邊緣觸發(edge-triggered)
        當文件描述符關聯的讀內核緩衝區由空轉化爲非空的時候,則發出可讀信號進行通知,
        當文件描述符關聯的內核寫緩衝區由滿轉化爲不滿的時候,則發出可寫信號進行通知

兩者的區別在哪裏呢?水平觸發是隻要讀緩衝區有數據,就會一直觸發可讀信號,而邊緣觸發僅僅在空變爲非空的時候通知一次,舉個例子:

    讀緩衝區剛開始是空的
    讀緩衝區寫入2KB數據
    水平觸發和邊緣觸發模式此時都會發出可讀信號
    收到信號通知後,讀取了1kb的數據,讀緩衝區還剩餘1KB數據
    水平觸發會再次進行通知,而邊緣觸發不會再進行通知

所以邊緣觸發需要一次性的把緩衝區的數據讀完爲止,也就是一直讀,直到讀到EGAIN爲止,EGAIN說明緩衝區已經空了,因爲這一點,邊緣觸發需要設置文件句柄爲非阻塞

//水平觸發
ret = read(fd, buf, sizeof(buf));

//邊緣觸發
while(true) {
    ret = read(fd, buf, sizeof(buf);
    if (ret == EAGAIN) break;
}

    1
    2
    3
    4
    5
    6
    7
    8

epoll接口介紹

    epoll_create
        創建epoll實例,會創建所需要的紅黑樹,以及就緒鏈表,以及代表epoll實例的文件句柄
        函數原型: int epoll_create(int size);
            Man文檔中說明了在老的內核版本中,入參size用來指出創建的內部數據結構的大小,目前已經可以動態調整,但是爲了兼容老的版本,所以仍然保留,這個size其實意義已經不大

    epoll_ctl
        添加,修改,或者刪除 註冊到epoll實例中的文件描述符上的監控事件

        int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
            epfd: epoll實例file descriptor

            op:操作類型

            EPOLL_CTL_ADD, 爲相應fd添加事件
            EPOLL_CTL_MOD, 修改fd的事件
            EPOLL_CTL_DEL,刪除fd上的某些事件
                1
                2
                3

            fd: 操作的目標文件描述符

            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 */
               };
               events可以是一組bit的組合
                EPOLLIN:可讀
                EPOLLOUT: 可寫
                EPOLLET: 邊緣觸發,默認是水平觸發
                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15

            一句話來描述:就是對於註冊到epfd中的fd文件描述符,執行op event的操作
    epoll_wait
        epoll_wait等待epoll實例中註冊的事件觸發
        int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
            epfd: epoll實例文件描述符
            events: 數組出參,用來記錄被觸發的events,其大小應該和maxevents一致
            maxevents: 返回的events的最大個數,如果最大個數大於實際觸發的個數,則下次epoll_wait的時候仍然可以返回
            timeout: 等待事件,毫秒爲單位 -1:無限等待 0:立即返回
 

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