發表文章

目前顯示的是 十月, 2016的文章

當 send 被 Block 的時候

今天在工作上遇到一個問題。有兩個 process ( process A 和 process B ) 透過 unix domain socket 彼此在傳遞資料,結果發現 process A 在送資料到 process B  的時候,程式居然卡在 send 這支系統函式。send 是會卡住的函式嗎?

答案是:會!來看看「男人」怎麼說:

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

When the message does not fit into the send  buffer  of  the  socket,  send()  normally blocks, unless the socket has been placed in nonblocking I/O mode.  In nonblocking mode it would fail with the error EAGAIN or EWOULDBLOCK in this case.   The  select(2)  call may be used to determine when it is possible to send more data.

意思是當呼叫 send 的時候,send 會先將資料放到 kernel 的 buffer,如果 buffer 已經放不進去了,而且 send 又處於 BLOCK 的模式時,這時候 send 就會卡住。而為什麼 buffer 會滿呢?因為 process B 處理封包的時間過久,進而造成 kernel buffer 被 process A 源源不絕的封包給塞滿了,然後 process A 的 send 就被 block 了。解決這個問題的方法可以將 socket 設成 non-blocking mode,或是在傳送封包的時候把 flag 設成 MSG_DONTWAIT。而這也就是為什麼 epoll, select 這類的函式需要去偵測 fd 是否已經是可寫狀態的原因。不過更根本要處理的問題是,為什麼 process B 會處理一個封包處理這麼久啊 ...

放上測試用的小程式:

unix domain socket receiver:
sleep(10) 用來模擬處理…