Libuv事件循環(huán)實(shí)現(xiàn)的邏輯是什么

這篇文章主要介紹“Libuv事件循環(huán)實(shí)現(xiàn)的邏輯是什么”,在日常操作中,相信很多人在Libuv事件循環(huán)實(shí)現(xiàn)的邏輯是什么問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Libuv事件循環(huán)實(shí)現(xiàn)的邏輯是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:申請(qǐng)域名網(wǎng)站空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、朝陽(yáng)縣網(wǎng)站維護(hù)、網(wǎng)站推廣。

Libuv是一個(gè)跨平臺(tái)的的基于事件驅(qū)動(dòng)的異步io庫(kù)。但是他提供的功能不僅僅是io,包括進(jìn)程、線程、信號(hào)、定時(shí)器、進(jìn)程間通信等。

  • Libuv使用各平臺(tái)提供的事件驅(qū)動(dòng)模塊實(shí)現(xiàn)異步(epoll, kqueue, IOCP, event
    ports)。他用來(lái)支持上層非文件io的模塊。libuv把上層的事件和回調(diào)封裝成io觀察者(uv__io_t)放到底層的事件驅(qū)動(dòng)模塊。當(dāng)事件觸發(fā)的時(shí)候,libuv會(huì)執(zhí)行io觀察者中的回調(diào)。

  • Libuv實(shí)現(xiàn)一個(gè)線程池用來(lái)支持上層文件io、DNS以及用戶層耗cpu的任務(wù)。

    Libuv的整體執(zhí)行架構(gòu)

Libuv事件循環(huán)實(shí)現(xiàn)的邏輯是什么  


從上圖中我們大致了解到,Libuv分為幾個(gè)階段,然后在一個(gè)循環(huán)里不斷執(zhí)行每個(gè)階段里的任務(wù)。下面我們具體看一下每個(gè)階段。

1 更新當(dāng)前事件,在每次事件循環(huán)開始的時(shí)候,libuv會(huì)更新當(dāng)前事件到變量中,這一輪循環(huán)的剩下操作可能使用這個(gè)變量獲取當(dāng)前事件,避免過多的系統(tǒng)調(diào)用影響性能。

2 如果時(shí)間循環(huán)是處于alive狀態(tài),則開始處理事件循環(huán)的每個(gè)階段。否則退出這個(gè)事件循環(huán)。alive狀態(tài)是什么意思呢?如果有active和ref狀態(tài)的handle,active狀態(tài)的request或者closing狀態(tài)的handle則認(rèn)為事件循環(huán)是alive的(具體實(shí)現(xiàn)后續(xù)會(huì)分析)。

3 timer階段:判斷最小堆中的節(jié)點(diǎn)哪個(gè)節(jié)點(diǎn)超時(shí)了,執(zhí)行他的回調(diào)。

4 pending階段:執(zhí)行pending回調(diào)。一般來(lái)說,所有的io回調(diào)(網(wǎng)絡(luò),文件,dns)都會(huì)在poll io階段執(zhí)行。但是有的情況下,poll io階段的回調(diào)會(huì)延遲到下一次循環(huán)執(zhí)行,那么這種回調(diào)就是在pending階段執(zhí)行的。

5 idle階段:如果節(jié)點(diǎn)處理avtive狀態(tài),每次事件循環(huán)都會(huì)被執(zhí)行(idle不是說事件循環(huán)空閑的時(shí)候才執(zhí)行)。

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

7 poll io階段:計(jì)算最長(zhǎng)等待時(shí)間timeout,計(jì)算規(guī)則:  
       如果時(shí)間循環(huán)是以UV_RUN_NOWAIT模式運(yùn)行的,則timeout是0。  
       如果時(shí)間循環(huán)即將退出(調(diào)用了uv_stop),則timeout是0。  
       如果沒有active狀態(tài)的handle或者request,timeout是0。  
       如果有dile階段的隊(duì)列里有節(jié)點(diǎn),則timeout是0。  
       如果有handle等待被關(guān)閉的(即調(diào)了uv_close),timeout是0。  
       如果上面的都不滿足,則取timer階段中最快超時(shí)的節(jié)點(diǎn)作為timeout,如果沒有則timeout等于-1,即永遠(yuǎn)阻塞,直到滿足條件。  
 

8 poll io階段:調(diào)用各平臺(tái)提供的io多路復(fù)用接口,最多等待timeout時(shí)間。返回的時(shí)候,執(zhí)行對(duì)應(yīng)的回調(diào)。(比如linux下就是epoll模式)

9 check階段:和idle prepare一樣。

10 closing階段:處理調(diào)用了uv_close函數(shù)的handle的回調(diào)。

11 如果libuv是以UV_RUN_ONCE模式運(yùn)行的,那事件循環(huán)即將退出。但是有一種情況是,poll io階段的timeout的值是timer階段的節(jié)點(diǎn)的值。并且poll io階段是因?yàn)槌瑫r(shí)返回的,即沒有任何事件發(fā)生,也沒有執(zhí)行任何io回調(diào)。這時(shí)候需要在執(zhí)行一次timer階段。因?yàn)橛泄?jié)點(diǎn)超時(shí)了。

12 一輪事件循環(huán)結(jié)束,如果libuv以UV_RUN_NOWAIT 或 UV_RUN_ONCE模式運(yùn)行的,則退出事件循環(huán)。如果是以UV_RUN_DEFAULT模式運(yùn)行的并且狀態(tài)是alive,則開始下一輪循環(huán)。否則退出事件循環(huán)。

下面是Libuv事件循環(huán)實(shí)現(xiàn)的邏輯。

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

    timeout = 0;
    // 執(zhí)行模式是UV_RUN_ONCE時(shí),如果沒有pending節(jié)點(diǎn),才會(huì)阻塞式poll io,默認(rèn)模式也是
    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
      timeout = uv_backend_timeout(loop);
    // poll io timeout是epoll_wait的超時(shí)時(shí)間
    uv__io_poll(loop, timeout);
    uv__run_check(loop);
    uv__run_closing_handles(loop);
    // 還有一次執(zhí)行超時(shí)回調(diào)的機(jī)會(huì),因?yàn)閜oll io階段可能是因?yàn)槎〞r(shí)器超時(shí)返回的。
    if (mode == UV_RUN_ONCE) {
      uv__update_time(loop);
      uv__run_timers(loop);
    }

    r = uv__loop_alive(loop);
    // 只執(zhí)行一次,退出循環(huán),UV_RUN_NOWAIT表示在poll io階段不會(huì)阻塞并且循環(huán)只執(zhí)行一次
    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
      break;
  }
  // 是因?yàn)檎{(diào)用了uv_stop退出的,重置flag
  if (loop->stop_flag != 0)
    loop->stop_flag = 0;
  // 返回是否還有活躍的任務(wù)(handle或request),業(yè)務(wù)代表可以再次執(zhí)行uv_run
  return r;

到此,關(guān)于“Libuv事件循環(huán)實(shí)現(xiàn)的邏輯是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

標(biāo)題名稱:Libuv事件循環(huán)實(shí)現(xiàn)的邏輯是什么
本文網(wǎng)址:http://www.muchs.cn/article42/iidjhc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計(jì)、響應(yīng)式網(wǎng)站、網(wǎng)站設(shè)計(jì)公司、虛擬主機(jī)云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司