說我的程序有一些線程,因爲文件描述符是在線程之間共享的,如果我調用close(stderr)
,所有的線程都不會輸出到stderr
。我的問題是:有一種方法可以在一個線程中關閉stderr
的輸出,但是不能在其他線程中輸出嗎?有沒有辦法在一個線程中關閉stderr的輸出,而不是其他線程?
更具體地說,我的程序的一個線程調用第三方庫函數,它保留輸出警告消息,我知道這些消息是無用的。但我無法訪問此第三方庫源。
說我的程序有一些線程,因爲文件描述符是在線程之間共享的,如果我調用close(stderr)
,所有的線程都不會輸出到stderr
。我的問題是:有一種方法可以在一個線程中關閉stderr
的輸出,但是不能在其他線程中輸出嗎?有沒有辦法在一個線程中關閉stderr的輸出,而不是其他線程?
更具體地說,我的程序的一個線程調用第三方庫函數,它保留輸出警告消息,我知道這些消息是無用的。但我無法訪問此第三方庫源。
編號文件描述符是進程中所有線程都可用的全局資源。標準錯誤當然是文件描述符編號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
而不是標準錯誤本身。這需要嚴格使用錯誤報告功能,但整個堆比一個額外的線程容易。
stderr
是每個進程不是每個線程,因此關閉它將關閉所有線程。
如果你想跳過特定的消息,可能你可以使用grep -v
。
在Linux上是可能給當前線程擁有自己的私人文件描述符表,使用<sched.h>
聲明的unshare()
功能:
unshare(CLONE_FILES);
這一呼籲後,你可以調用close(2);
,它會影響只有當前線程。
但請注意,一旦文件描述符表是非共享的,就不能再回到共享它 - 這是單向操作。這也是Linux特有的,所以它不是可移植的。
這真的很有幫助,因爲這個想法也可以在其他情況下使用。 –
請注意,完整的建議步驟稍微複雜一些。您需要首先複製標準錯誤描述符(2),然後使用'fclose(stderr)',然後打開描述符以寫入'/ dev/null',然後將其移至描述符2,然後將'stderr = fdopen(2, 「wb」)',然後打開'others_stderr = fdopen(n,「wb」)'其中'n'是stderr最初被複制的描述符,因此您可以安全地執行標準stdio.h I/O冒着混淆的風險。然後您可以執行'fprintf(others_stderr,...)'等來將您真實的錯誤消息寫入原始標準錯誤。 –