C 中的分叉和指针
Forks and Pointers in C
有人可以帮助我了解系统如何处理在进程进行 fork()
调用之前设置的变量。下面是我写的一个小测试程序,试图了解幕后发生的事情。
我了解进程的当前状态是 "cloned",包括变量,在分叉时。我的想法是,如果我在调用 fork 之前 malloc 一个二维数组,我将需要在父进程和子进程中释放该数组。
正如您从示例代码下方的结果中看到的那样,这两个值的行为就好像它们彼此完全独立,但它们具有完全相同的地址 space。我预计 tmp 的最终结果将是 -4
,无论哪个进程先完成。
我是 C 和 Linux 的新手,所以有人可以解释一下这是怎么可能的吗?也许变量 tmp 成为指向每个进程中不同的指针的指针?非常感谢。
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int tmp = 1;
pid_t forkReturn= fork();
if(!forkReturn) {
/*child*/
tmp=tmp+5;
printf("Value for child %d\n",tmp);
printf("Address for child %p\n",&tmp);
}
else if(forkReturn > 0){
/*parent*/
tmp=tmp-10;
printf("Value for parent %d\n",tmp);
printf("Address for parent %p\n",&tmp);
}
else {
/*Error calling fork*/
printf("Error calling fork);
}
return 0;
}
标准输出结果:
Value for child 6
Address for child 0xbfb478d8
Value for parent -9
Address for parent 0xbfb478d8
它确实复制了整个地址space,并且在child进程中更改内存不会影响parent。理解这一点的关键是要记住指针只能指向你自己进程中的某些东西,而复制发生在较低级别。
但是,您根本不应该在 fork 的 child 中调用 malloc() 或 free()。这可能会死锁(当您调用 fork() 时另一个线程在 malloc() 中)。在 child 中唯一可以安全调用的函数是那些也被列为对信号处理程序安全的函数。我曾经能够声称只有当你编写多线程代码时这是真的;然而 Apple 非常友好地在标准库中生成了一个后台线程,因此死锁一直都是真实存在的。 fork 的 child 绝对不允许从 if 块中删除。调用 _exit 以确保它没有。
有人可以帮助我了解系统如何处理在进程进行 fork()
调用之前设置的变量。下面是我写的一个小测试程序,试图了解幕后发生的事情。
我了解进程的当前状态是 "cloned",包括变量,在分叉时。我的想法是,如果我在调用 fork 之前 malloc 一个二维数组,我将需要在父进程和子进程中释放该数组。
正如您从示例代码下方的结果中看到的那样,这两个值的行为就好像它们彼此完全独立,但它们具有完全相同的地址 space。我预计 tmp 的最终结果将是 -4
,无论哪个进程先完成。
我是 C 和 Linux 的新手,所以有人可以解释一下这是怎么可能的吗?也许变量 tmp 成为指向每个进程中不同的指针的指针?非常感谢。
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int tmp = 1;
pid_t forkReturn= fork();
if(!forkReturn) {
/*child*/
tmp=tmp+5;
printf("Value for child %d\n",tmp);
printf("Address for child %p\n",&tmp);
}
else if(forkReturn > 0){
/*parent*/
tmp=tmp-10;
printf("Value for parent %d\n",tmp);
printf("Address for parent %p\n",&tmp);
}
else {
/*Error calling fork*/
printf("Error calling fork);
}
return 0;
}
标准输出结果:
Value for child 6
Address for child 0xbfb478d8
Value for parent -9
Address for parent 0xbfb478d8
它确实复制了整个地址space,并且在child进程中更改内存不会影响parent。理解这一点的关键是要记住指针只能指向你自己进程中的某些东西,而复制发生在较低级别。
但是,您根本不应该在 fork 的 child 中调用 malloc() 或 free()。这可能会死锁(当您调用 fork() 时另一个线程在 malloc() 中)。在 child 中唯一可以安全调用的函数是那些也被列为对信号处理程序安全的函数。我曾经能够声称只有当你编写多线程代码时这是真的;然而 Apple 非常友好地在标准库中生成了一个后台线程,因此死锁一直都是真实存在的。 fork 的 child 绝对不允许从 if 块中删除。调用 _exit 以确保它没有。