linux fork 写时拷贝的本质

linux fork 写时拷贝的本质

作者:admin |  时间:2015-05-04 |  浏览:2434 |  0 条评论

在做linux c编程的时候,我们知道进程fork的时候,有一个copy on write的机制,关于这个概念可能有的朋友还不是很清楚,我们拿一段程序来说明一下:

#include<stdio.h>
#include<unistd.h>
int main (void)
{
  int *p = malloc(sizeof(int));
  *p = 0;
  printf("start main()\n");
  int pid = fork();
    
  if (pid == 0) {
    printf("i am child, my pid is %d\n", getpid());
    printf("before written, address of p=0x%x\n", p);
    *p += 5;
    printf("after written, address of p=0x%x\n", p);
    printf("value of p=%d\n", *p);
    return 0;
  } else {
    printf("i am parent, my pid is %d\n", getpid());
    printf("before written, address of p=0x%x\n", p);
    *p += 2;
    printf("after written, address of p=0x%x\n", p);
    printf("value of p=%d\n", *p);
    return 0;printf("value of p=%d\n", *p);
    return 0;
  }
}

执行结果如下:

root@tocore-desktop:~# ./jin
start main()
i am parent, my pid is 3983
before written, address of p=0x8cdd008
after written, address of p=0x8cdd008
value of p=2
root@tocore-desktop:~# i am child, my pid is 3984
before written, address of p=0x8cdd008
after written, address of p=0x8cdd008
value of p=5

看到这里,可能有的朋友奇怪了,p的地址无论在父进程还是子进程都是一样的,那为什么在父子进程中,p的值不一样呢?

这里就涉及到了fork的copy on write机制。什么意思呢?我们知道,在fork出子进程后:

(1)在父子进程都没有写操作前(比如修改变量等),父子进程共用同一个进程空间(进程空间内的地址都是虚拟内存地址,比如p的地址0x8cdd008), 共用同一个进程空间的本质,就是共用同一份页目录表和页表,共用同一份页目录表和页表的结果,就是父子进程空间的虚拟内存地址都映射到相同的物理地址,我 们假设p的地址0x8cdd008都被映射到物理地址0×20000004,所以,父子进程访问到的所有数据都是一样的(当然这里只针对数据段

(2)当父子进程其中一个有写操作时,比如修改子进程p的值为5, 那么内核会为子进程的p变量的虚拟内存地址,也就是0x8cdd008重新建立和物理地址的映射,比如重新映射到物理地址0×20000008并将此地址 标记为已用。这是通过修改子进程的页目录表和页表来实现的。所以,这个时候才算是真正的为子进程的变量p分配了物理地址0×20000008。

这就是copy on write的好处,在保证父子进程正常工作的前提下,最大程度上节省物理内存空间和提高系统性能。

转:http://www.linux2web.net/?p=554

相关推荐

发表评论

电子邮件地址不会被公开。

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>