天天看點

epoll的作用和原理介紹

  背景開發,網絡互動是必須的,而epoll基本絕大多數網絡架構的必備武器,本文對epoll進行詳細的介紹,包括epoll的作用,優點,接口,實作原理等。

一. epoll是什麼

  epoll是一種IO多路轉接技術,在LINUX網絡程式設計中,經常用來做事件觸發,即當有特定事件到來時,能夠檢測到,而不必阻塞進行監聽。

  epoll有兩種工作方式,ET-水準觸發 和 LT-邊緣觸發(預設工作方式),主要的差別是:

  LT,核心通知你fd是否就緒,如果沒有處理,則會持續通知。而ET,核心隻通知一次。

二. epoll的優點

  與select相比,epoll有以下優點:

  2.1. 支援程序打開大量數目的socket描述符,select支援的程序描述符由FD_SETSIZE設定,預設值為

     1024,而epoll不受這個限制。

  2.2. epoll的效率,不随監聽的socket數目增加而線性下降。

     select采用輪詢的方式,對socket集合的描述符表進行掃描,如果socket數量過大,并且大多數

     socket屬于idle狀态,select的掃描就做了很多無用功。

     epoll隻會對活躍的socket進行操作,是以,在socket數量比較大,而絕大多數socket屬于idle

     狀态時,epoll的效率會遠勝于select。如果絕大多數socket是活躍的,由于epoll_ctl的影響,

     epoll的效率會稍微比select差。

  3.3. 使用mmap加速核心與使用者空間的傳遞,關于mmap,找個時間做個詳細的介紹。

三. epoll的接口

  epoll主要有三個接口

  3.1 int epoll_create( int size )

    建立一個epoll的句柄,size表示監聽的數目一共有多大,我們現網的伺服器,每個程序是設定    

    12W。

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

    事件注冊函數,epfd是epoll_create傳回的句柄,op是表示做什麼動作,用三個宏表示:

        EPOLL_CTL_ADD:注冊新的fd到epfd中;

        EPOLL_CTL_MOD:修改已經注冊的fd的監聽事件;

        EPOLL_CTL_DEL:從epfd中删除一個fd;

        fd表示要監聽的描述符,event表示核心要監聽什麼事,由以下幾個宏表示:

        EPOLLIN :表示對應的檔案描述符可以讀(包括對端SOCKET正常關閉);

        EPOLLOUT:表示對應的檔案描述符可以寫;

        EPOLLPRI:表示對應的檔案描述符有緊急的資料可讀;

        EPOLLERR:表示對應的檔案描述符發生錯誤;

        EPOLLHUP:表示對應的檔案描述符被挂斷;

        EPOLLET: 将EPOLL設為邊緣觸發(Edge Triggered)模式,這是相對于水準觸發(Level Triggered)來說的。

        EPOLLONESHOT:隻監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把     

       這個socket加入到EPOLL隊列裡

  3.3 int epoll_wait( int epfd, struct epoll_event* events, int maxevents, int time_out )

    等待事件的發生。events,存儲epoll_wait操作完成後,存儲的事件。maxevents表示目前要監聽的

    所有socket句柄數。time_out為逾時時間。傳回值表示需要處理的事件數目,0表示逾時。

四. epoll的實作原理

     epoll_create

     在epoll檔案系統建立了個file節點,并開辟epoll自己的核心高速cache區,建立紅黑樹,配置設定

     好想要的size的記憶體對象,建立一個list連結清單,用于存儲準備就緒的事件。  

     epoll_ctl

     把要監聽的socket放到對應的紅黑樹上,給核心中斷處理程式注冊一個回調函數,通知核心,如果

     這個句柄的資料到了,就把它放到就緒清單。

     epoll_wait

     觀察就緒清單裡面有沒有資料,并進行提取和清空就緒清單,非常高效。

     LT和ET實作的差別?

     由epoll_wait進行實作,如果是LT模式,它發現soket上還有未處理的事件,則在清理就緒清單

繼續閱讀