2013-05-30 20 views
1

說我的程序有一些線程,因爲文件描述符是在線程之間共享的,如果我調用close(stderr),所有的線程都不會輸出到stderr。我的問題是:有一種方法可以在一個線程中關閉stderr的輸出,但是不能在其他線程中輸出嗎?有沒有辦法在一個線程中關閉stderr的輸出,而不是其他線程?

更具體地說,我的程序的一個線程調用第三方庫函數,它保留輸出警告消息,我知道這些消息是無用的。但我無法訪問此第三方庫源。

回答

3

編號文件描述符是進程中所有線程都可用的全局資源。標準錯誤當然是文件描述符編號2,所以它是一個全局資源,不能阻止第三方代碼寫入它。

如果問題嚴重到足以保證治療,你可以這樣做:

int fd2_copy = dup(2); 
int fd2_null = open("/dev/null", O_WRONLY); 

在調用第三方庫函數:

dup2(fd2_null, 2); 
third_party_library_function(); 
dup2(fd2_copy, 2); 

基本上,第三的持續時間第四方庫,將標準錯誤切換到/dev/null,恢復該功能後恢復正常輸出。

您當然應該錯誤地檢查系統調用。

這樣做的缺點是,雖然此線程正在執行第三方函數,但任何其他需要寫入標準錯誤的線程也會寫入/dev/null

您可能不得不考慮添加可與「第三方庫執行線程」(TPLET)同步的「錯誤寫入線程」(EWT)。其他線程會向EWT寫入消息。如果TPLET正在執行第三方庫,則EWT將等待完成,然後才寫入任何排隊的消息。(雖然這將「工作」,這是艱苦的工作。)解決此

一種方法是將有由通用代碼(不是第三方庫的代碼等)使用的錯誤報告功能寫入fd2_copy而不是標準錯誤本身。這需要嚴格使用錯誤報告功能,但整個堆比一個額外的線程容易。

+0

這真的很有幫助,因爲這個想法也可以在其他情況下使用。 –

+0

請注意,完整的建議步驟稍微複雜一些。您需要首先複製標準錯誤描述符(2),然後使用'fclose(stderr)',然後打開描述符以寫入'/ dev/null',然後將其移至描述符2,然後將'stderr = fdopen(2, 「wb」)',然後打開'others_stderr = fdopen(n,「wb」)'其中'n'是stderr最初被複制的描述符,因此您可以安全地執行標準stdio.h I/O冒着混淆的風險。然後您可以執行'fprintf(others_stderr,...)'等來將您真實的錯誤消息寫入原始標準錯誤。 –

2

stderr是每個進程不是每個線程,因此關閉它將關閉所有線程。

如果你想跳過特定的消息,可能你可以使用grep -v

2

在Linux上可能給當前線程擁有自己的私人文件描述符表,使用<sched.h>聲明的unshare()功能:

unshare(CLONE_FILES); 

這一呼籲後,你可以調用close(2);,它會影響只有當前線程。

但請注意,一旦文件描述符表是非共享的,就不能再回到共享它 - 這是單向操作。這也是Linux特有的,所以它不是可移植的。

相關問題