我试图用叉子来使用类似的代码是从多线程的父执子计划:使用管道在多线程程序与孩子沟通
#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
管道是本地的,但打开的文件描述符对进程是全局的。只有当所有打开的描述符关闭时,管道才会关闭,并且叉可能无意中创建您不了解的描述符的副本。 –
我看到问题,我不知道更好的解决方案。分叉和线程不能很好地协同工作,至今我还没有听到任何解决方案。 –