使用fork产生的子进程复制了父进程的代码段和数据段,
我们现在假定在父进程中有一个变量var,初始值为88
子进程也有一个var,初始值也是88,修改子进程的var,父进程的var并不改变
而且父进程和子进程的代码段和数据段是完全一样的,
所以父进程和子进程中var的逻辑地址也是完全一样的,
{
逻辑地址实际上是段内偏移量,就是该变量在该进程空间中数据段的偏移量
要求得他的物理地址,要根据操纵系统的段式内存管理方法,来求得他的物理地址
}
所以如果此时输出来两个var的地址  printf("%d",&var);得到的两个地址是一样的,因为得到的是逻辑地址,但是他们两个的物理地址是不一样的。

如果使用vfork()就一样的了,父子进程共享数据段,代码段
注意fork并不是调用后就复制父进程的堆栈,而是只有在对数据段进行写操作时候才复制的,这种机制叫COW
即copy on write
考试时候这个可是很有可能考的诶~~
所以如果程序这样写,就不会拷贝堆栈了

还需要注意的一点是fork后父子进程的运行先后顺序是不确定的,而vfork则是先运行子进程,阻塞父进程,知道子进程退出。

来看输出结果

由fork()和vfork()回忆下OS的内存管理_linux

看明白哪里不对头了么?
地址一样,但是值却不一样,为什么呢?看下面你就明白了!

再回忆一下OS的内存管理方法。
逻辑地址转换成线性地址,线性地址通过CPU的页式内存管理方法来转换成物理地址
而逻辑地址转换成线性地址的方法是:
段标识符+段内偏移量。
在Linux里面其实段标识符是0,所以在Linux里面逻辑地址就等于线性地址。他们是一致的。
在CPU的页式内存管理中,把线性地址(Linux里面即逻辑地址,因为Linux中从逻辑地址到线性地址的转换就是欺骗OS的)分为若干固定长度的单元,成为页,
如果以4K为单位,在32位机器中,线性地址最大可达到4G,那么线性地址就被划分为2^20方个页,每一个页有一个地址,我们称之为 页地址。
另一类“页”,我们叫做物理页,或者是页框,他把物理内存也划分为固定长度的管理单位,它的长度一般和内存也是一一对应的。
然后OS会进行调度,分别把页框和对应的页进行匹配起来。