我試圖用叉子來使用類似的代碼是從多線程的父執子計劃:使用管道在多線程程序與孩子溝通
#include <thread>
#include <unistd.h>
#include <vector>
#include <sys/wait.h>
void printWithCat(const std::string& data) {
std::vector<char*> commandLine;
// exec won't change argument so safe cast
commandLine.push_back(const_cast<char*>("cat"));
commandLine.push_back(0);
int pipes[2];
pipe(pipes);
// Race condition here
pid_t pid = fork();
if (pid == 0) {
// Redirect pipes[0] to stdin
close(pipes[1]);
close(0);
dup(pipes[0]);
close(pipes[0]);
execvp("cat", &commandLine.front());
}
else {
close(pipes[0]);
write(pipes[1], (void*)(data.data()), data.size());
close(pipes[1]);
waitpid(pid, NULL, 0);
}
}
int main()
{
std::thread t1(printWithCat, "Hello, ");
std::thread t2(printWithCat, "World!");
t1.join();
t2.join();
}
此代碼包含調用之間的競爭條件,以管對叉子的呼叫。如果兩個線程都創建了管道然後fork,那麼每個子進程都包含對兩個管道的打開文件描述符,並且只關閉一個。結果是管道永遠不會關閉,子進程永遠不會退出。我目前將管道和fork調用包裝在一個全局鎖中,但是這增加了一個額外的同步。有沒有更好的辦法?
你肯定有一個競爭條件?管道是一個局部變量,所以每個線程都有自己的副本。 – paj28
管道是本地的,但打開的文件描述符對進程是全局的。只有當所有打開的描述符關閉時,管道纔會關閉,並且叉可能無意中創建您不瞭解的描述符的副本。 –
我看到問題,我不知道更好的解決方案。分叉和線程不能很好地協同工作,至今我還沒有聽到任何解決方案。 –