輸入輸出系統與裝置管理

事件通知介面(an event-notification interface)

想像你是一位櫃台接待,看顧著二十支電話。你不能拿起一支、在它上面等待,而讓其他支沒人接地響著。你想要的是一個會亮燈、告訴你「第 3 與第 17 支現在需要你」的面板,讓你只處理那幾支、忽略沉默的那些。事件通知介面就是輸入輸出的那塊面板:一個系統呼叫,程式透過它同時看顧許多檔案描述符,並被告知哪些已就緒可讀或可寫,於是它只服務那些。

具體來說,這些介面讓一條執行緒監看許多來源。用 select 或 poll,程式把它在意的一串檔案描述符交給作業系統,並下達像「當其中任何一個可讀時就喚醒我」的請求。這個呼叫阻塞,直到至少一個就緒,然後返回那個就緒的集合;程式服務那些,再問一次。經典版本(select、poll)每次呼叫都重新掃描整串清單,當描述符達數千時就變慢。於是 Linux 加上了 epoll(BSD 加上了 kqueue),你只登記一次興趣,核心就維護一份持續更新的清單,只返回真正變為就緒的描述符——把一次 O(n) 的掃描變成更接近 O(就緒事件數)。這些是事件驅動與非同步輸入輸出底下的就緒積木。

為什麼重要:這正是一條單執行緒的伺服器能處理數萬條連線、卻不必為每條連線生出一條執行緒(那會浪費記憶體與排程心力)的方法。它是網頁伺服器、資料庫與非同步執行環境中事件迴圈的核心。要釐清一個誠實的區別:select/poll/epoll 告訴你某個描述符已就緒(你仍得自己發出讀或寫),而真正的非同步輸入輸出介面則替你執行操作、並在它完成時告訴你——就緒通知與完成通知相關,但並不相同。

一個聊天伺服器有 10000 條開啟的通訊端。它呼叫一次 epoll_wait;核心只返回此刻有新訊息的那 12 條。伺服器只讀那 12 條,然後迴圈回去——一條執行緒、沒有忙碌等待、不必一客戶端一執行緒。

用一次呼叫看顧許多描述符;只對作業系統回報為就緒的那些採取行動。

這些介面回報的是就緒、而非完成:epoll 告訴你某條通訊端可讀,並沒有搬移任何資料——你仍要呼叫 read。這個區別正是以就緒為基礎的輸入輸出多工,與真正的非同步輸入輸出之間的分界。

又称
selectpollepollI/O multiplexingreadiness notification事件多工