原则上,在C++中使用这些函数没有问题,但您必须知道共享哪些数据以及如何共享.
考虑一下,fork()新进程获取父进程内存的完整副本(使用copy-on-write).内存是状态,因此你有两个独立的进程必须留下干净的状态.
现在,只要你保持在给予你的记忆范围内,你就不应该有任何问题:
#include <iostream>
#include <unistd.h>
class Foo {
public:
Foo () { std::cout << "Foo():" << this << std::endl; }
~Foo() { std::cout << "~Foo():" << this << std::endl; }
Foo (Foo const &) {
std::cout << "Foo::Foo():" << this << std::endl;
}
Foo& operator= (Foo const &) {
std::cout << "Foo::operator=():" << this<< std::endl;
return *this;
}
};
int main () {
Foo foo;
int pid = fork();
if (pid > 0) {
// We are parent.
int childExitStatus;
waitpid(pid, &childExitStatus, 0); // wait until child exits
} else if (pid == 0) {
// We are the new process.
} else {
// fork() failed.
}
}
Run Code Online (Sandbox Code Playgroud)
以上程序将大致打印:
Foo():0xbfb8b26f
~Foo():0xbfb8b26f
~Foo():0xbfb8b26f
Run Code Online (Sandbox Code Playgroud)
不会发生复制构造或复制分配,操作系统将进行按位复制.地址是相同的,因为它们不是物理地址,而是指向每个进程的虚拟内存空间的指针.
当两个实例共享信息时变得更加困难,例如在退出之前必须刷新和关闭的打开文件:
#include <iostream>
#include <fstream>
int main () {
std::ofstream of ("meh");
srand(clock());
int pid = fork();
if (pid > 0) {
// We are parent.
sleep(rand()%3);
of << "parent" << std::endl;
int childExitStatus;
waitpid(pid, &childExitStatus, 0); // wait until child exits
} else if (pid == 0) {
// We are the new process.
sleep(rand()%3);
of << "child" << std::endl;
} else {
// fork() failed.
}
}
Run Code Online (Sandbox Code Playgroud)
这可能会打印
parent
Run Code Online (Sandbox Code Playgroud)
要么
child
parent
Run Code Online (Sandbox Code Playgroud)
或者是其他东西.
问题是这两个实例不足以协调它们对同一文件的访问,并且您不知道实现细节std::ofstream.
(可能的)解决方案可以在"进程间通信"或"IPC"这两个术语下找到,最近的解决方案是waitpid():
#include <unistd.h>
#include <sys/wait.h>
int main () {
pid_t pid = fork();
if (pid > 0) {
int childExitStatus;
waitpid(pid, &childExitStatus, 0); // wait until child exits
} else if (pid == 0) {
...
} else {
// fork() failed.
}
}
Run Code Online (Sandbox Code Playgroud)
最简单的解决方案是确保每个进程仅使用自己的虚拟内存,而不是其他任何内容.
另一种解决方案是Linux特定的解决方案:确保子流程不会清理.操作系统将对所有获取的内存进行原始的非RAII清理,并关闭所有打开的文件,而不会刷新它们.如果您使用fork()它exec()来运行另一个进程,这可能很有用:
#include <unistd.h>
#include <sys/wait.h>
int main () {
pid_t pid = fork();
if (pid > 0) {
// We are parent.
int childExitStatus;
waitpid(pid, &childExitStatus, 0);
} else if (pid == 0) {
// We are the new process.
execlp("echo", "echo", "hello, exec", (char*)0);
// only here if exec failed
} else {
// fork() failed.
}
}
Run Code Online (Sandbox Code Playgroud)
退出而不触发任何更多析构exit()函数的另一种方法是函数.我通常建议不要在C++中使用,但在分叉时,它有它的位置.
| 归档时间: |
|
| 查看次数: |
1637 次 |
| 最近记录: |