最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
怎么處理Accept出現(xiàn)Emfile的問題

這篇文章主要介紹了怎么處理Accept出現(xiàn)Emfile的問題,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

公司主營業(yè)務(wù):成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。成都創(chuàng)新互聯(lián)是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴謹、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)推出順德免費做網(wǎng)站回饋大家。

通常情況下,服務(wù)端調(diào)用 accept 函數(shù)會返回一個新的文件描述符,用于和客戶端之間的數(shù)據(jù)傳輸

服務(wù)器的開發(fā)中,有時會遇到這種情況:當調(diào)用 accept 函數(shù)接受客戶端連接,函數(shù)返回失敗,對應(yīng)的錯誤碼是 EMFILE,  它表示當前進程打開的文件描述符已達上限,此時,服務(wù)器不能再接受客戶端連接

當遇到上述問題,怎么合理的處理呢,下面就來分析一下

建立連接的流程

先簡單回顧下客戶端和服務(wù)器建立連接的流程,具體的如下圖所示:

怎么處理Accept出現(xiàn)Emfile的問題

1. 客戶端發(fā)起 SYN 請求

2. 服務(wù)器收到客戶端的 SYN 請求后,內(nèi)核把連接放入半連接隊列,同時給客戶端返回一個 SYN + ACK

3. 客戶端向服務(wù)器返回一個確認的 ACK, 服務(wù)器收到本次 ACK  之后,三次握手完成,同時,內(nèi)核把連接從半連接隊列中移除,創(chuàng)建新完全連接,加入到全連接隊列中

4. 應(yīng)用層調(diào)用 accept 函數(shù)從全連接隊列中取出連接

上面的第 1、第 2、第 3 步是 TCP 的三次握手,它是由內(nèi)核中TCP協(xié)議完成的, 第 4 步是應(yīng)用層調(diào)用 accept 接口

在 epoll 中的問題

epoll 是 Linux中IO多路復(fù)用模型,在服務(wù)器的開發(fā)中有廣泛的應(yīng)用,下面就以 epoll 為例來詳細說明

服務(wù)器端創(chuàng)建偵聽文件描述符 listenfd 之后, 向 epoll 注冊讀事件

當 epoll 檢測到 listenfd 上有讀事件發(fā)生,會立即通知應(yīng)用層,應(yīng)用層調(diào)用 accept  接受新連接,而此時進程打開的文件描述符數(shù)量已經(jīng)達到上限了,所以每次 accept 都是失敗的

這里會出現(xiàn)以下幾個問題

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 由于 每次 accept 都失敗了,相當于 listenfd 上的可讀事件沒有處理,epoll 會不停的觸發(fā) listenfd  上的可讀事件,應(yīng)用層也就會不停的調(diào)用 accept,然后又出現(xiàn) accept 調(diào)用失敗,如此這般不停的執(zhí)行無效的循環(huán),白白浪費了CPU的資源

  3. 上面提到服務(wù)器在不停的執(zhí)行無效的循環(huán), 將會引發(fā)另一個問題,如果此時有新客戶端連接到來,建立連接的過程會很慢

前面說的 epoll 默認是使用了水平觸發(fā)模式,如果使用垂直觸發(fā)模式會出現(xiàn)什么問題呢?

垂直觸發(fā)模式下,listenfd 從無讀事件狀態(tài)到有讀事件狀態(tài)時,才會通知到應(yīng)用層,在應(yīng)用層處理完 listenfd 上所有的讀事件之前,epoll  不會再通知應(yīng)用層

也就是說,應(yīng)用層收到 listenfd 上讀事件通知之后,需要把 listenfd 上所有的讀事件全部處理完,下次listenfd  上再有讀事件時,才會通知應(yīng)用層

回到 accept 的問題上,在垂直觸發(fā)模式下,當 epoll 通知應(yīng)用層 listenfd 上有可讀事件時,應(yīng)用層調(diào)用 accept,  由于此時進程打開的文件描述符數(shù)量已經(jīng)達到上限了,所以 accept 調(diào)用失敗

也即 listenfd 上的可讀事件還沒有處理,在應(yīng)用層處理完 listenfd 上可讀事件之前,epoll 不會再通知應(yīng)用層 listenfd  上有可讀事件

如果在應(yīng)用層處理完 listenfd 上可讀事件之前,有新的客戶端連接到來,這個時候 epoll 是不會通知應(yīng)用層 listenfd  上有可讀事件,這會導(dǎo)致一個嚴重的問題:accept 只要出現(xiàn)了 EMFILE的錯誤碼,就再也無法接受客戶端的連接了

所以,當出現(xiàn) EMFILE 時,不管使用 epoll 的水平觸發(fā)模式還是垂直觸發(fā)模式都會存在問題

如何解決

EMFILE 表示進程打開的文件描述符數(shù)量達到上限了,可以把這個值調(diào)大些,但這治標不治本

本來系統(tǒng)設(shè)置文件描述符數(shù)量上限是為了限制進程對系統(tǒng)資源的過度占用,況且,這個值調(diào)整到多大合適呢,總不能無限大吧,所以調(diào)整上限值的方式不是最合適的方式

accept 成功時會返回一個新的文件描述符,如果此時進程打開的文件描述符數(shù)量已經(jīng)達到上限了,就會返回失敗

假如此時能關(guān)閉一個空閑的文件描述符,讓出一個名額,再調(diào)用 accept 就會創(chuàng)建成功,這種方式具體的處理步驟如下:

1、事先準備一個空閑的文件描述符 idlefd,相當于先占一個"坑"位

2、調(diào)用 close 關(guān)閉 idlefd,關(guān)閉之后,進程就會獲得一個文件描述符名額

3、再次調(diào)用 accept 函數(shù), 此時就會返回新的文件描述符 clientfd, 立刻調(diào)用 close 函數(shù),關(guān)閉 clientfd

4、重新創(chuàng)建空閑文件描述符 idlefd,重新占領(lǐng) "坑" 位,再出現(xiàn)這種情況的時候又可以使用

由于測試代碼比較長,這里就不貼了,感興趣可以通過文末的方式獲取,下面是處理 EMFILE 的偽代碼:

int ret = accept( listenfd, (struct sockaddr*)&addr, sizeof(addr) );  if (-1 == ret) {   if ( errno == EMFILE )   {      //關(guān)閉空閑文件描述符,釋放 "坑"位      close(idlefd);            //接受 clientfd      clientfd = accept( listenfd, nullptr, nullptr);      //關(guān)閉 clientfd,防止一直觸發(fā) listenfd 上的可讀事件      close(clientfd);            //重新占領(lǐng) "坑"位      idlefd = ::open("/dev/null", O_RDONLY | O_CLOEXEC);   } }

感謝你能夠認真閱讀完這篇文章,希望小編分享的“怎么處理Accept出現(xiàn)Emfile的問題”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!


本文名稱:怎么處理Accept出現(xiàn)Emfile的問題
當前路徑:http://fisionsoft.com.cn/article/jpcdsh.html