2012-04-30 22 views
3

我有一個父進程和派生的子進程,它們共享一個Unix域套接字IPC與socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)創建。這兩個進程關閉socketpair的一端,並將另一端保存到sock變量中。之後,他們做到這一點:的Unix IPC插座:關閉一端而不閱讀它

int sock; // Unix-domain socket 

void child_main() 
{ 
    printf("I am child\n");  
    sleep(1);  
    close(sock); 
} 

void parent_main() 
{ 
    printf("I am parent\n"); 

    write(sock, "hello", 5); 

    char buf[100]; 
    int ret = read(sock, buf, 100); // this read will return ECONNRESET 
    if (ret == -1) { 
    perror("read"); 
    exit(-1); 
    } 
} 

父過程中的一些數據寫入到插座,孩子讀它。相反,孩子關閉了插座。現在我擔心的是父進程中的read失敗,ECONNRESET(連接重置對等),而我期望它會返回「0」表示流結束。因爲插座的另一端是優雅關閉通過呼籲close

現在,我明白這種行爲(關閉套接字沒有讀取待處理的數據產生ECONNRESET),但如果是這樣記錄? man read隻字未提ECONNRESET,但它提到:可能出現

其他錯誤,根據連接到的fd對象

man page for unix domain sockets只是說上:

ECONNRESET:遠程套接字意外關閉。

但是由於Unix域套接字是一個本地IPC事物,我認爲它可以更具體地描述這種錯誤發生的情況。

我的「深思」是這樣的:如果說規範例如close只有在沒有數據要從套接字中讀取時纔會生成流結束標記,它如何​​知道其他進程是不是隻寫一些?這不會造成競爭狀態嗎?內核如何知道連接是否將被正常關閉?

+0

不太確定這是否會有所幫助,但是您是否在'close()'之前嘗試過使用'shutdown()'? – Hasturkun

+0

我剛試過,並使用'shutdown(); close();'表現相同,但使用'shutdown();睡眠(1); close();'實際上正常關閉連接。所以它似乎創造了一個競賽條件,當套接字的另一端「輪到」轉速足夠快時,它會沒事的。所以這是不必要的,我不能稱之爲「睡眠(...)」。 – kuba

回答

2

使用有狀態套接字(unix域或tcp),區分「無數據」和在另一端關閉套接字的最佳方式是首先使用select(),傳遞一個readfds(請參見man 2選擇)。如果,並且只有在select指示一個讀事件時,然後嘗試在套接字上讀()。如果讀取的字節數爲0,則表示套接字已關閉(由對等方重置連接)。