日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

libev源码解析——I/O模型

發布時間:2023/11/27 生活经验 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 libev源码解析——I/O模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ? 在《libev源碼解析——總覽》一文中,我們介紹過,libev是一個基于事件的循環庫。本文將介紹其和事件及循環之間的關系。(轉載請指明出于breaksoftware的csdn博客)

? ? ? ? 目前ibev支持如下IO事件模型:

  • select模型。對應文件是ev_select.c。
  • poll模型。對應文件是ev_poll.c。
  • epoll模型。對應的文件是ev_epoll.c。
  • port模型。對應文件是ev_port.c。
  • kqueue模型。對應的文件是ev_kqueue.c。
  • iocp模型。即IO完成端口模型(I/O Completion Port)。

? ? ? ? 這些模型并不是我們這個系列介紹的重點。如果想了解select、poll、epoll模型,可以參閱《樸素、Select、Poll和Epoll網絡編程模型實現和分析》系列博文。(下圖是select模型的調用邏輯圖)

? ? ? ??

? ? ? ? 此處我們只要知道它們是libev可選的事件模型即可。至于選擇什么模型。要視loop_init的入參flags。

static void noinline ecb_cold
loop_init (EV_P_ unsigned int flags) EV_THROW
{
……
#if EV_USE_IOCPif (!backend && (flags & EVBACKEND_IOCP  )) backend = iocp_init   (EV_A_ flags);
#endif
#if EV_USE_PORTif (!backend && (flags & EVBACKEND_PORT  )) backend = port_init   (EV_A_ flags);
#endif
#if EV_USE_KQUEUEif (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags);
#endif
#if EV_USE_EPOLLif (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init  (EV_A_ flags);
#endif
#if EV_USE_POLLif (!backend && (flags & EVBACKEND_POLL  )) backend = poll_init   (EV_A_ flags);
#endif
#if EV_USE_SELECTif (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
#endif
……
}

? ? ? ? backend是一個用于記錄libev使用的是哪種IO模型的標記位。

? ? ? ? 在每個模型初始化函數中,都需要指定兩個模型相關的函數指針。比如epoll模型的初始化函數epoll_init中

int inline_size
epoll_init (EV_P_ int flags)
{
……backend_mintime = 1e-3; /* epoll does sometimes return early, this is just to avoid the worst */backend_modify  = epoll_modify;backend_poll    = epoll_poll;
……
}

? ? ? ? 而在select模型中則是

int inline_size
select_init (EV_P_ int flags)
{backend_mintime = 1e-6;backend_modify  = select_modify;backend_poll    = select_poll;
……
}

? ? ? ? backend_mintime是需要等待事件的超時秒數;backend_modify是輪詢中修改事件信息的函數。backend_poll則是等待事件的函數。libev通過上述四個變量,隔離了不同模型選擇導致不同函數調用的問題。

? ? ? ? 但是這兒需要指出的是,libev并沒有將這種隔離做徹底。因為在關閉IO模型時,它仍然依靠backend的值,調用了不同函數(ev_loop_destroy中)

#if EV_USE_IOCPif (backend == EVBACKEND_IOCP  ) iocp_destroy   (EV_A);
#endif
#if EV_USE_PORTif (backend == EVBACKEND_PORT  ) port_destroy   (EV_A);
#endif
#if EV_USE_KQUEUEif (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A);
#endif
#if EV_USE_EPOLLif (backend == EVBACKEND_EPOLL ) epoll_destroy  (EV_A);
#endif
#if EV_USE_POLLif (backend == EVBACKEND_POLL  ) poll_destroy   (EV_A);
#endif
#if EV_USE_SELECTif (backend == EVBACKEND_SELECT) select_destroy (EV_A);
#endif

? ? ? ? 個人認為,可以在各個模型的初始化中,將其對應的銷毀函數指針賦值給一個叫backend_destory的變量。這樣上述代表就可以變成一行了。

? ? ? ? 結合《libev源碼解析——調度策略》的內容,我們可以用下圖表達出libev運轉的大體流程。

? ? ? ? 針對上圖,可能有人會問:為什么backend_poll函數需要指定超時?我們讓其一直等待到有事件發生不是更好么?

? ? ? ? 還有人會問:“符合條件的監視器”是否可以表述為“本次觸發事件對應的監視器”?

? ? ? ? 對于這些問題,我們將在之后章節給出答案。

總結

以上是生活随笔為你收集整理的libev源码解析——I/O模型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。