I/O多路複用技術(multiplexing)
I/O多路複用技術(multiplexing)是什麼?
I/O多路複用技術(multiplexing)是
關於I/O多路複用(又被稱為“事件驅動”),首先要理解的是,作業系統為你提供了一個功能,當你的某個socket可讀或者可寫的時候,它可以給你一個通知。這樣當配合非阻塞的socket使用時,只有當系統通知我哪個描述符可讀了,我才去執行read操作,可以保證每次read都能讀到有效資料而不做純返回-1和EAGAIN的無用功。寫操作類似。作業系統的這個功能通過select/poll/epoll/kqueue之類的系統呼叫函式來使用,這些函式都可以同時監視多個描述符的讀寫就緒狀況,這樣,多個描述符的I/O操作都能在一個執行緒內併發交替地順序完成,這就叫I/O多路複用,這裡的“複用”指的是複用同一個執行緒。
以select和tcp socket為例,所謂可讀事件,具體的說是指以下事件:
1 socket核心接收緩衝區中的可用位元組數大於或等於其低水位SO_RCVLOWAT;
2 socket通訊的對方關閉了連線,這個時候在緩衝區裡有個檔案結束符EOF,此時讀操作將返回0;
3 監聽socket的backlog佇列有已經完成三次握手的連線請求,可以呼叫accept;
4 socket上有未處理的錯誤,此時可以用getsockopt來讀取和清除該錯誤。
所謂可寫事件,則是指:
1 socket的核心傳送緩衝區的可用位元組數大於或等於其低水位SO_SNDLOWAIT;
2 socket的寫端被關閉,繼續寫會收到SIGPIPE訊號;
3 非阻塞模式下,connect返回之後,發起連線成功或失敗;
4 socket上有未處理的錯誤,此時可以用getsockopt來讀取和清除該錯誤。
Linux環境下,Redis資料庫伺服器大部分時間以單程式單執行緒模式執行(執行持久化BGSAVE任務時會開啟子程式),網路部分屬於Reactor模式,同步非阻塞模型,即非阻塞的socket檔案描述符號加上監控這些描述符的I/O多路複用機制(在Linux下可以使用select/poll/epoll)。伺服器執行時主要關注兩大型別事件:檔案事件和時間事件。檔案事件指的是socket檔案描述符的讀寫就緒情況,時間事件分為一次性定時器和週期性定時器。相比nginx和haproxy內建的高精度高效能定時器,redis的定時器機制並不那麼先進複雜,它只用了一個連結串列來管理時間事件,而且目前連結串列也沒有對各個事件的到點時間進行排序,也就是說,每次都要遍歷連結串列檢查每個事件是否需要到點執行。個人猜想是因為redis目前並沒有太多的定時事件需要管理,redis以資料庫伺服器角色執行時,定時任務回撥函式只有位於redis/src/redis.c下的serverCron函式,所有的定時任務都在這個函式下執行,也就是說,連結串列裡面其實目前就一個節點元素,所以目前也無需實現高效能定時器。
Redis網路事件驅動模型程式碼:redis/src/目錄下的ae.c, ae.h, ae_epoll.c, ae_evport.c, ae_select.c, ae_kqueue.c , ae_evport.c。其中ae.c/ae.h:標頭檔案裡定義了描述檔案事件和事件時間的結構體, 即aeFileEvent和aeTimeEvent;事件驅動狀態結構體aeEventLoop, 這個結構體只有一個名為eventloop的全域性變數在整個伺服器程式中;事件就緒回撥函式指標aeFileProc和aeTimeProc;以及操作事件驅動模型的各種API(aeCreateEventLoop以及之後全部的函式宣告)。ae_epoll.c, ae_select.c, ae_keque.c和ae_evport.c封裝了select/epoll/kqueue等系統呼叫,Linux下當然不支援kqueue和evport。至於究竟選擇哪一種I/O多路複用技術,在ae.c裡有預處理控制,也就是說,這些原始檔只有一個能最後被編譯。優先選擇epoll或者kqueue(FREEBSD和Mac OSX可用),其次是select。
redis事件驅動整體流程:redis伺服器main函式位於檔案redis/src/redis.c, 事件驅動入口函式位於main函式的倒數第三行:相關文章
- Netty權威指南:I/O 多路複用技術Netty
- 一文搞懂I/O多路複用及其技術
- 【Linux網路程式設計】I/O 多路複用技術Linux程式設計
- 多路I/O複用:select、poll、epoll(二)
- 從網路I/O模型到Netty,先深入瞭解下I/O多路複用模型Netty
- LinuxI/O多路複用Linux
- 詳解Go語言I/O多路複用netpoller模型Go模型
- IO多路複用技術總結
- 【面試】I/O 複用面試
- 一篇文章幫你徹底搞清楚“I/O多路複用”和“非同步I/O”的前世今生非同步
- Go netpoll I/O 多路複用構建原生網路模型之原始碼深度解析Go模型原始碼
- Linux下的5種I/O模型與3組I/O複用Linux模型
- 網路程式設計-I/O複用程式設計
- 多路複用
- 理解IO多路複用
- IO多路複用詳解
- IO多路複用小故事
- Redis 和 IO 多路複用Redis
- 計算機網路——多路複用與多路分解計算機網路
- Linux I/O 原理和 Zero-copy 技術全面揭祕Linux
- 玩轉 PHP 網路程式設計全套之 I/O 複用PHP程式設計
- [Java併發]IO多路複用Java
- 徹底搞懂IO多路複用
- IO多路複用原理&場景
- BIO、NIO、多路複用IO、AIOAI
- 作業系統I/O模型及輪詢技術演變作業系統模型
- IO多路複用機制詳解
- IO多路複用(一)– Select、Poll、Epoll
- I/O複用3個小例項+將signal轉化為IO事件事件
- 計算機I/O與I/O模型計算機模型
- I/O程式設計技術(檔案IO)筆記綱要梳理程式設計筆記
- Java I/O流 複製檔案速度對比Java
- 細談 Linux 中的多路複用epollLinux
- IO通訊模型(三)多路複用IO模型
- 如何基於 Channel 實現多路複用
- 用bonnie++測試磁碟I/O
- Google I/O 2022: 促進知識和計算機技術發展Go計算機
- Java I/OJava