2017-10-18 174 views
1

我有一個庫,它註冊了atfork處理程序(通過pthread_atfork()),它在調用fork()時不支持多線程。在我的情況下,我不需要使用分叉環境,因爲我只需要在fork()之後立即致電exec()。所以,我想fork(),但沒有任何atfork處理程序。那可能嗎?我錯過任何重要的邊緣情況嗎?fork + exec無atfork處理程序

對於背景信息,庫是OpenBlas,問題描述爲herehere

+0

如果OpenBlas註冊了一個atfork處理函數,通常*在多線程程序中不能可靠地工作,那麼OpenBlas在這方面就有問題了。 'pthread_atfork()'沒有其他用例。如果這確實是OpenBlas的一個問題,並且你不準備自己修復它或者等待維護人員修復它,那麼你最好的選擇可能是選擇一個不同的BLAS庫。 –

回答

1

您可以使用vfork()(NPTL實現不調用fork處理程序)。儘管POSIX從標準中刪除了vfork,但它很可能在您的實施中可用。使用pthread_atfork建立

叉處理程序(3)當 採用NPTL線程庫多線程程序調用vfork的 不叫()。在這種情況下,叉處理程序在使用LinuxThreads線程庫的程序中調用。 (參見用於Linux線程庫的 描述並行線程(7)。)

或者,posix_spawn()。這與vfork類似。手冊頁上說:

根據POSIX,它未指定在調用posix_spawn()時是否調用使用pthread_atfork(3)建立的fork處理函數。在glibc上,只有在使用fork(2)創建孩子時纔會調用fork處理程序。

或者,syscall並直接使用SYS_cloneSYS_clone是用於在Linux上創建線程和進程的系統調用號。所以syscall(SYS_clone, SIGCHLD, 0);應該工作,只要你立即執行。

syscall(SYS_fork);(由Shachar回答)可能也會起作用。但請注意,SYS_fork在某些平臺上不可用(例如,aarch64,ia64)。 SYS_fork在Linux中被認爲是過時的,它只是爲了向後兼容,而Linux內核使用SYS_clone來創建所有「類型」的進程。

(注意:這些選項大多限於glibc/Linux)。

1

是的。以下應工作在Linux(和,我想,所有glibc基於平臺):

#define _GNU_SOURCE 
#include <unistd.h> 
#include <sys/syscall.h> 

... 
    syscall(SYS_fork); 

這繞過圖書館,直接調用系統調用fork。如果您的平臺未將fork作爲單個系統調用實施,則可能會遇到麻煩。對於Linux,這僅僅意味着您應該使用clone來代替。

考慮到這一點,我不確定我會這樣做。既然你是圖書館,你不知道爲什麼有人註冊了atfork。假設不相關的是糟糕的編程習慣。

因此,你失去了可移植性,以做一些可能或不可能破壞的東西,所有的名稱,什麼?保存幾個函數調用?就個人而言,我只是使用fork

+0

請注意,如果在您的實現中可以使用此方法,則可以直接調用fork()。它沒有解決間接調用'fork()'的情況,比如通過'system()'或'popen()'來調用。 –

+0

我想沒有辦法讓代碼更獨立於平臺,例如對於MacOSX,我需要其他代碼?另一個問題:如果我打算在'fork()'後面調用'exec()',那麼可能會有什麼原因可以運行任何atfork處理程序? – Albert

+0

@Albert但是你的C庫的fork不知道你要立即執行;-)即使這樣做了,它仍然不能跳過fork處理程序,因爲它需要在每個文檔中運行它們。也許,如果你正在尋找便攜性,'posix_spawn'是你最好的選擇。 – usr