## 引言:從“阻塞”的餐廳到“事件驅動”的盛宴
想象一下,你是一家小餐館的服務員。餐廳只有5張桌子。你的工作流程是這樣的:走到1號桌,問他們是否要點菜,然后站在那里等他們決定;等他們點完,再去2號桌,同樣站在那里等... 如果1號桌的客人看菜單看了半個小時,那么其他桌的客人就會餓肚子,甚至憤然離場。
這種“一個接一個,必須等前一個完成才能服務下一個”的模式,就是典型的 **阻塞 I/O**。在網絡編程中,如果一個服務器用這種方式處理連接(`accept`)和讀寫(`read`, `write`),那它的并發能力將極其低下,只能服務極少數客戶端。
再想象一家更高級的餐廳。你,作為服務員,不再傻站在一桌旁等待。你的流程變成了:首先巡視全場,依次詢問每一桌:“您好,現在需要點菜嗎?”“菜好了,請慢用。”“需要加菜嗎?”。如果某桌客人說“我們還沒想好”,你就先跳過他們,去問下一桌。等巡視完一圈,你又從頭開始新一輪的詢問。
這種“一次性收集所有客戶需求,然后統一處理”的模式,就是 **I/O 多路復用** 的核心思想。你(服務器進程)就像一個高效的經理,同時“監視”著多個客人(文件描述符),誰準備好了(可讀/可寫/異常)就處理誰,而不是被任何一個客人阻塞住。
在 Linux 中,實現這種“高效巡視”的經典方法就是 `select` 和 `poll`。本文將帶你深入實戰,徹底掌握它們。
---
## 第一部分:內核的監視器 - Select
### 1.1 Select 的工作原理
`select` 系統調用允許進程指示內核等待多個文件描述符中的任何一個變為“就緒”狀態(如可讀、可寫或發生異常),或者經歷一段指定的時間后返回。