91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Libuv事件循環實現的邏輯是什么

發布時間:2021-12-17 09:27:50 來源:億速云 閱讀:304 作者:iii 欄目:大數據

這篇文章主要介紹“Libuv事件循環實現的邏輯是什么”,在日常操作中,相信很多人在Libuv事件循環實現的邏輯是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Libuv事件循環實現的邏輯是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Libuv是一個跨平臺的的基于事件驅動的異步io庫。但是他提供的功能不僅僅是io,包括進程、線程、信號、定時器、進程間通信等。

  • Libuv使用各平臺提供的事件驅動模塊實現異步(epoll, kqueue, IOCP, event
    ports)。他用來支持上層非文件io的模塊。libuv把上層的事件和回調封裝成io觀察者(uv__io_t)放到底層的事件驅動模塊。當事件觸發的時候,libuv會執行io觀察者中的回調。

  • Libuv實現一個線程池用來支持上層文件io、dns以及用戶層耗cpu的任務。

    Libuv的整體執行架構

Libuv事件循環實現的邏輯是什么  


從上圖中我們大致了解到,Libuv分為幾個階段,然后在一個循環里不斷執行每個階段里的任務。下面我們具體看一下每個階段。

1 更新當前事件,在每次事件循環開始的時候,libuv會更新當前事件到變量中,這一輪循環的剩下操作可能使用這個變量獲取當前事件,避免過多的系統調用影響性能。

2 如果時間循環是處于alive狀態,則開始處理事件循環的每個階段。否則退出這個事件循環。alive狀態是什么意思呢?如果有active和ref狀態的handle,active狀態的request或者closing狀態的handle則認為事件循環是alive的(具體實現后續會分析)。

3 timer階段:判斷最小堆中的節點哪個節點超時了,執行他的回調。

4 pending階段:執行pending回調。一般來說,所有的io回調(網絡,文件,dns)都會在poll io階段執行。但是有的情況下,poll io階段的回調會延遲到下一次循環執行,那么這種回調就是在pending階段執行的。

5 idle階段:如果節點處理avtive狀態,每次事件循環都會被執行(idle不是說事件循環空閑的時候才執行)。

6 prepare階段:和idle階段一樣。

7 poll io階段:計算最長等待時間timeout,計算規則:  
       如果時間循環是以UV_RUN_NOWAIT模式運行的,則timeout是0。  
       如果時間循環即將退出(調用了uv_stop),則timeout是0。  
       如果沒有active狀態的handle或者request,timeout是0。  
       如果有dile階段的隊列里有節點,則timeout是0。  
       如果有handle等待被關閉的(即調了uv_close),timeout是0。  
       如果上面的都不滿足,則取timer階段中最快超時的節點作為timeout,如果沒有則timeout等于-1,即永遠阻塞,直到滿足條件。  
 

8 poll io階段:調用各平臺提供的io多路復用接口,最多等待timeout時間。返回的時候,執行對應的回調。(比如linux下就是epoll模式)

9 check階段:和idle prepare一樣。

10 closing階段:處理調用了uv_close函數的handle的回調。

11 如果libuv是以UV_RUN_ONCE模式運行的,那事件循環即將退出。但是有一種情況是,poll io階段的timeout的值是timer階段的節點的值。并且poll io階段是因為超時返回的,即沒有任何事件發生,也沒有執行任何io回調。這時候需要在執行一次timer階段。因為有節點超時了。

12 一輪事件循環結束,如果libuv以UV_RUN_NOWAIT 或 UV_RUN_ONCE模式運行的,則退出事件循環。如果是以UV_RUN_DEFAULT模式運行的并且狀態是alive,則開始下一輪循環。否則退出事件循環。

下面是Libuv事件循環實現的邏輯。

int uv_run(uv_loop_t* loop, uv_run_mode mode) {
  int timeout;
  int r;
  int ran_pending;
  // 在uv_run之前要先提交任務到loop
  r = uv__loop_alive(loop);
  // 事件循環沒有任務執行,即將退出,設置一下當前循環的時間
  if (!r)
    uv__update_time(loop);
  // 沒有任務需要處理或者調用了uv_stop 
  while (r != 0 && loop->stop_flag == 0) {
    // 更新loop的time字段
    uv__update_time(loop);
    // 執行超時回調
    uv__run_timers(loop);
    // 執行pending回調,ran_pending代表pending隊列是否為空,即沒有節點可以執行
    ran_pending = uv__run_pending(loop);
    // 繼續執行各種隊列
    uv__run_idle(loop);
    uv__run_prepare(loop);

    timeout = 0;
    // 執行模式是UV_RUN_ONCE時,如果沒有pending節點,才會阻塞式poll io,默認模式也是
    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
      timeout = uv_backend_timeout(loop);
    // poll io timeout是epoll_wait的超時時間
    uv__io_poll(loop, timeout);
    uv__run_check(loop);
    uv__run_closing_handles(loop);
    // 還有一次執行超時回調的機會,因為poll io階段可能是因為定時器超時返回的。
    if (mode == UV_RUN_ONCE) {
      uv__update_time(loop);
      uv__run_timers(loop);
    }

    r = uv__loop_alive(loop);
    // 只執行一次,退出循環,UV_RUN_NOWAIT表示在poll io階段不會阻塞并且循環只執行一次
    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
      break;
  }
  // 是因為調用了uv_stop退出的,重置flag
  if (loop->stop_flag != 0)
    loop->stop_flag = 0;
  // 返回是否還有活躍的任務(handle或request),業務代表可以再次執行uv_run
  return r;

到此,關于“Libuv事件循環實現的邏輯是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

潮州市| 太保市| 大渡口区| 安图县| 富裕县| 丰台区| 岫岩| 新龙县| 平和县| 历史| 汉寿县| 奇台县| 盱眙县| 西华县| 高台县| 襄垣县| 郑州市| 延安市| 宁强县| 离岛区| 黄龙县| 曲松县| 宁乡县| 吉安市| 调兵山市| 新化县| 西峡县| 开化县| 新沂市| 阿瓦提县| 富源县| 平原县| 永年县| 盐源县| 利川市| 车险| 云浮市| 张家口市| 米易县| 西贡区| 桦川县|