Socket

有沒有權威的地方說接受偵聽套接字的多程序或執行緒是原子操作?

  • August 23, 2020

當我閱讀有關 Nginx 的一些材料時,我注意到在單個套接字上接受傳入連接的兩種傳統方法之一是:

在單個埠上執行的多執行緒伺服器使用的第二種傳統方法是讓所有執行緒(或程序)accept()在一個簡單的事件循環中對單個偵聽套接字執行呼叫:

 while (1) {
        new_fd = accept(...);
        process_connection(new_fd);
    }

引用自SO_REUSEPORT 套接字選項

然後我注意到 Nginx 似乎也使用了這種方法。

如圖所示,當該SO_REUSEPORT選項未啟用時,單個偵聽套接字會通知工作人員有關傳入的連接,並且每個工作人員都嘗試建立連接。

Nginx socket 接受模型圖

引自NGINX 版本 1.9.1 中的套接字分片

Aagin,在開源應用程序架構(第 2 卷):nginx中,使用關鍵字搜尋頁面accept,其中寫道:

如前所述,nginx 不會為每個連接生成一個程序或執行緒。相反,**工作程序接受來自共享“監聽”套接字的新請求,並在每個工作人員內部執行高效的執行循環,以處理每個工作人員的數千個連接。**nginx 中沒有專門的仲裁或連接分配給工作人員;這項工作是由作業系統核心機製完成的。


所以我真的很震驚,因為沒有人告訴我在各種程序或執行緒之間接受一個監聽套接字是可以的並且不會導致競爭條件

因為當提到使用共享資源時,我首先想到的是“那個函式呼叫執行緒安全嗎”?所以我用Google搜尋並在 StackOverflow 上找到了一個相關的問題。

accept() 執行緒安全嗎?

接受的答案再次證明了這種行為,但它根本沒有提供參考,評論下的人們仍在爭論官方文件從哪裡定義這一點。

到那時,我認為 by 給出的屬性thread-safe是不夠的,因為它表示單個偵聽套接字上的多個執行緒或程序。 accept我需要比這更強大的東西。

所以我來查看這本書The Linux Programming Interface,在*§5.1 Atomicity and Race Conditions*中,它寫道:

原子性是我們在討論系統呼叫的操作時會反复遇到的一個概念。各種系統呼叫操作以原子方式執行。我們的意思是核心保證操作中的所有步驟都在不被另一個程序或執行緒中斷的情況下完成。

原子性對於成功完成某些操作至關重要。特別是,它允許我們避免競爭條件(有時稱為競爭危險)。競爭條件是這樣一種情況,其中兩個程序(或執行緒)在共享資源上執行所產生的結果以一種意想不到的方式取決於程序獲得對 CPU 的訪問權的相對順序。

所以我需要的詞/屬性是atmoicatomicity

所以我的問題是:

有沒有權威的地方說接受偵聽套接字的多程序或執行緒是原子操作?

經過數小時的搜尋,我只是在網上找不到任何參考資料。

https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html

accept() 被列為“非同步信號安全”函式。下面解釋所有非同步信號安全函式都是執行緒安全的。列出了執行緒安全的特定例外,例如未鎖定的 stdio 函式,並且未提及 accept()。

需要注意的是,accept 是一個系統呼叫。系統呼叫不是執行緒安全的沒有任何意義,因為這意味著核心不是執行緒安全的!

核心必須是執行緒安全的,因此系統呼叫也必須是執行緒安全的。

引用自:https://unix.stackexchange.com/questions/605832