reproc(重定向程序)是一個跨平台 C/C++ 函式庫,可簡化外部程式的啟動、停止和通訊。主要用例是直接從 C 或 C++ 程式碼執行命令列應用程式並檢索其輸出。
reproc 由兩個函式庫組成:reproc 和 reproc++。 reproc 是一個 C99 函式庫,包含使用外部程式的實際程式碼。 reproc++ 依賴 reproc 並將其 API 調整為慣用的 C++11 API。它還添加了一些額外功能,可以簡化 C++ 外部程式的使用。
#include <reproc/run.h>
int main ( void )
{
const char * args [] = { "echo" , "Hello, world!" , NULL };
return reproc_run ( args , ( reproc_options ) { 0 });
}
如果您在閱讀自述文件和文件後有任何疑問,您可以提出問題或直接在 reproc gitter 頻道中提問。
注意:建置 reproc 需要 CMake 3.12 或更高版本。
有多種方法可以將 reproc 引入到您的專案中。一種方法是使用 CMake 將 reproc 建構成專案的一部分。為此,我們首先必須將 reproc 原始碼放入專案中。可以使用以下任一選項來完成此操作:
FetchContent
API 下載 reproc。有關範例,請參閱 https://cliutils.gitlab.io/modern-cmake/chapters/projects/fetch.html。在專案中包含 reproc 的原始程式碼後,可以從根 CMakeLists.txt 檔案建置它,如下所示:
add_subdirectory (< path -to-reproc>) # For example: add_subdirectory(external/reproc)
可以在呼叫add_subdirectory
之前指定 CMake 選項:
set (REPROC++ ON )
add_subdirectory (< path -to-reproc>)
注意:如果該選項已在先前的 CMake 運行中緩存,則必須清除 CMake 的快取才能套用新的預設值。
有關配置 reproc 建置的更多信息,請參閱 CMake 選項。
您也可以依賴已安裝的 reproc 版本。您可以自行建置和安裝 reproc,也可以透過套件管理器安裝 reproc。 reproc 可在以下軟體包儲存庫中找到:
如果無法使用套件管理器,您可以從原始程式碼建置並安裝 reproc (CMake 3.13+):
cmake -B build
cmake --build build
cmake --install build
啟用REPROC_TEST
選項並建置test
目標以執行測試(CMake 3.13+):
cmake -B build -DREPROC_TEST=ON
cmake --build build
cmake --build build --target test
安裝 reproc 後,您的建置系統將必須找到它。 reproc 提供 CMake 設定檔和 pkg-config 文件,以簡化分別使用 CMake 和 pkg-config 來尋找 reproc 安裝的過程。請注意,reproc 和 reproc++ 是單獨的函式庫,因此也有單獨的設定檔。請務必搜尋您要使用的。
若要使用 CMake 尋找已安裝的 reproc 版本:
find_package (reproc) # Find reproc.
find_package (reproc++) # Find reproc++.
將 reproc 建置為專案的一部分或找到已安裝的 reproc 版本後,您可以從 CMakeLists.txt 檔案中連結到它,如下所示:
target_link_libraries (myapp reproc) # Link against reproc.
target_link_libraries (myapp reproc++) # Link against reproc++.
從 Meson 0.53.2 開始,reproc 可以作為 CMake 子專案包含在 Meson 建置腳本中。請參閱 https://mesonbuild.com/CMake-module.html 以了解更多資訊。
預設情況下,reproc 依賴 POSIX 系統上的 pthreads ( -pthread
) 和 Windows 系統上的 Winsock 2.2 ( -lws2_32
) 相依性。 CMake 和 pkg-config 會自動處理這些依賴項。
reproc 的建置可以使用以下 CMake 選項進行配置:
REPROC++
:建構 reproc++ (預設值: ${REPROC_DEVELOP}
)
REPROC_TEST
:建置測試(預設值: ${REPROC_DEVELOP}
)
透過執行測試二進位檔案來執行測試,該二進位test
可以在建置 reproc 後在建置目錄中找到。
REPROC_EXAMPLES
:建置範例(預設值: ${REPROC_DEVELOP}
)
產生 reproc 後,產生的二進位檔案將位於生成目錄中每個項目子目錄的範例資料夾中。
REPROC_OBJECT_LIBRARIES
:建立 CMake 物件庫(預設值: ${REPROC_DEVELOP}
)
這對於直接將 reproc 包含在另一個庫中非常有用。當 reproc 建置為靜態或共用程式庫時,它必須與使用程式庫一起安裝,這使得分發使用程式庫變得更加困難。使用物件庫時,reproc 的物件檔案直接包含在使用庫中,無需額外安裝。
注意:reproc 的物件庫只能從 CMake 3.14 開始正確連結。
注意:此選項會覆蓋BUILD_SHARED_LIBS
。
REPROC_INSTALL
:產生安裝規則(預設值: ON
,除非啟用REPROC_OBJECT_LIBRARIES
)
REPROC_INSTALL_CMAKECONFIGDIR
:CMake 設定檔安裝目錄(預設: ${CMAKE_INSTALL_LIBDIR}/cmake
)
REPROC_INSTALL_PKGCONFIG
:安裝 pkg-config 檔案(預設值: ON
)
REPROC_INSTALL_PKGCONFIGDIR
:pkg-config 檔案安裝目錄(預設: ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
REPROC_MULTITHREADED
:使用pthread_sigmask
並連結到系統的執行緒庫(預設值: ON
)
REPROC_DEVELOP
:配置開發選項預設值(預設值: OFF
除非設定了REPROC_DEVELOP
環境變數)REPROC_SANITIZERS
:使用消毒劑建置(預設值: ${REPROC_DEVELOP}
)REPROC_TIDY
:建置時執行 clang-tidy (預設值: ${REPROC_DEVELOP}
)REPROC_WARNINGS
:啟用編譯器警告(預設值: ${REPROC_DEVELOP}
)REPROC_WARNINGS_AS_ERRORS
:新增 -Werror 或等效於編譯標誌和 clang-tidy (預設值: OFF
) 每個函數和類別都在其頭檔中進行了詳細記錄。範例可以在reproc 和reproc++ 的examples 子目錄中找到。
失敗時,reproc API 中的大多數函數都會傳回負errno
(POSIX) 或GetLastError
(Windows) 樣式的錯誤代碼。對於可操作的錯誤,reproc 提供常數( REPROC_ETIMEDOUT
、 REPROC_EPIPE
等),可用於匹配錯誤,而無需編寫特定於平台的程式碼。若要取得錯誤的字串表示形式,請將其傳遞給reproc_strerror
。
reproc++ 的 API 與 C++ 標準函式庫錯誤程式碼機制( std::error_code
和std::error_condition
)整合。 reproc++ API 中的大多數方法都會傳回包含實際發生的系統錯誤的std::error_code
值。您可以使用std::errc
枚舉中的值來測試這些錯誤代碼。
有關如何在使用 reproc 時處理錯誤的更多信息,請參閱範例。
筆記:
reproc 和 reproc++ API 都採用options
參數,該參數可以定義一個或多個stop
操作,例如terminate
或kill
。因此,如果使用 POSIX 上的訊號終止或殺死子進程,錯誤代碼將不會反映錯誤。
由下游項目來解釋反映意外行為的狀態代碼以及錯誤代碼(請參閱此範例)。
不要同時從多個執行緒對同一個子進程呼叫相同的操作。例如:從不同執行緒讀取和寫入子程序沒問題,但同時從兩個不同執行緒等待同一個子程序會導致問題。
(POSIX) 強烈建議不要對 reproc 啟動的程序的 pid 呼叫waitpid
。
reproc 使用waitpid
等待進程退出。不幸的是, waitpid
不能在同一進程上呼叫兩次。這表示如果在 reproc 之外之前已經在子進程上呼叫了waitpid
,則reproc_wait
將無法正常運作。
強烈建議使用reproc_wait
或reproc_stop
確保每個子程序實際退出。
在 POSIX 上,已退出的子程序是殭屍進程,直到父進程使用waitpid
等待它。殭屍進程會佔用資源,可以被視為資源洩漏,因此確保所有進程及時正確退出非常重要。
強烈建議嘗試透過等待子程序退出或在訴諸reproc_kill
之前呼叫reproc_terminate
來終止子程序。
使用reproc_kill
時,子程序沒有機會執行清理,這可能會導致資源洩漏。這些洩漏中最主要的是子進程將無法停止自己的子進程。始終嘗試透過在呼叫reproc_kill
之前呼叫reproc_terminate
讓子程序正常退出。 reproc_stop
是一個方便的輔助函數,可用於連續執行多個停止操作,中間有逾時。
(POSIX) 強烈建議忽略父行程中的SIGPIPE
訊號。
在 POSIX 上,預設情況下,寫入子程序的關閉 stdin 管道將使用SIGPIPE
訊號終止父進程。為了避免這種情況,必須在父進程中忽略SIGPIPE
訊號。如果忽略SIGPIPE
訊號,則在寫入關閉的標準輸入管道時, reproc_write
將如預期返回REPROC_EPIPE
。
雖然reproc_terminate
允許子程序執行清理,但由子程序自行完成正確的清理工作。 reproc 只向子程序發送終止訊號。子進程本身負責清理自己的子進程和其他資源。
(Windows) reproc_kill
無法保證在 Windows 上立即終止子程序。有關詳細信息,請閱讀 Windows TerminateProcess
函數文件中的「備註」部分,reproc 使用該函數來終止 Windows 上的子進程。
透過 reproc 產生的子程序繼承一個額外的檔案句柄,用於等待子程序退出。如果子進程手動關閉這個檔案句柄,reproc會錯誤地偵測到子進程已經退出。如果該句柄進一步被比子進程壽命更長的其他進程繼承,reproc 將偵測到子進程仍在運行,即使它已經退出。如果向這個句柄寫入數據,reproc也會錯誤地偵測到子程序已經退出。
(Windows) 無法偵測子程序在退出之前是否關閉其 stdout 或 stderr 流。只有當子進程退出時,父進程才會收到子進程輸出流已關閉的通知。
(Windows) reproc 假定 Windows 建立可用作檔案系統物件的套接字。更具體地說, WSASocket
回傳的預設套接字應該會設定XP1_IFS_HANDLES
標誌。如果 Windows 電腦上安裝了外部 LSP 提供者,則情況可能並非如此。如果是這種情況,我們建議刪除提供額外服務提供者的軟體,因為它們已被棄用,不應再使用(請參閱https://docs.microsoft.com/en-us/windows/win32/winsock /對分層服務提供者和應用程式進行分類)。