??调用fork函数可以在已存在的进程中创建一个子进程,此时,新进程叫做子进程,原进程叫做父进程。
??#include <unistd.h>
??pid_t fork(void);
?其中pid_t的底层是int;
返回值::子进程中返回0,父进程返回子进程id,出错返回-1
也就是这样:
#include <iostream>
#include <unistd.h>
int main()
{
pid_t fd = fork();
if (fd == 0)
{
//this area is child
}
else if(fd > 0)
{
// this area is parent
}
else
{
// this area is error
}
return 0;
}
??当我们在用户空间调用了fork以后,控制会从用户空间转移到内核空间,因为fork属于系统调用,然后内核会:
??由于虚拟内存地址和页表以及页表和物理地址空间的映射关系,父子进程此时都是一模一样的。所以可以说父子继承一开始都是使用同一块地址空间。
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int a = 8;
pid_t fd = fork();
if (fd == 0)
{
a = 3;
std::cout << "child: " << a << std::endl;
}
if (fd > 0)
{
std::cout << "parent: " << a << std::endl;
}
wait(NULL);
return 0;
}
??看完上面这份代码,为什么明明父子进程的a是同一块地址空间的,按理来说子进程修改了a为3,父进程的a为什么还是8呢?难道是结论错误了吗?
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int a = 8;
std::cout << &a << std::endl;
pid_t fd = fork();
if (fd == 0)
{
a = 3;
std::cout << "child: " << &a << std::endl;
}
if (fd > 0)
{
std::cout << "parent: " << &a << std::endl;
}
wait(NULL);
return 0;
}
??通过上面这个代码也可以清楚知道父子进程的a指向的地址空间确实是同一个。
??这里的原因是因为我们所看到的地址叫做虚拟内存空间,每一个进程都会有一份虚拟内存和一个页表。但是物理内存只有一个,页表中保存着虚拟内存和物理内存之间的一份映射关系。
??我们可以浅显的将页表看做下图(真正页表中的字段不止三个,但是此刻这三个字段足以说明问题);
??所以真实情况是:子进程的创建确实以父进程为模板将其内容拷贝到了子进程的内核数据结构中,但是当数据有所变化时,就以深拷贝的方式父子进程各自私有一份。
????😄 创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看😄