微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

分叉后的虚拟和物理地址

如何解决分叉后的虚拟和物理地址

在分叉之后,子进程的虚拟地址空间在后台发生了什么?

我一直在阅读其他文章,但是有些人的说法与其他人的说法背道而驰,这有点弄乱了我的主意。

以下面的代码为例:

int main(int argc,char const *argv[])
{
    int a = 5;

    dummy(&a);

    return 0;
}

void dummy(int * a){
    if(fork()==0){
        printf("%p",a);
        *a=10;
    }
    else{
       printf("%p",a);
       printf("%d\n",*a); //a is still 5
    }
}

为什么在两个printf之后%p的值都相同,但是当我在子级中更改a的值时,它不会反映在父级上。打印%p时,它是指变量的虚拟地址吗?

子级的虚拟地址和父级的虚拟地址是否相同(在对堆进行任何更改之前), 还是新的子进程具有自己的虚拟地址,该地址指向父进程的相同物理地址(只要不对堆中的变量进行任何更改)?

我已经读到,对位于子堆上的变量进行更改时,将克隆物理内存,并且虚拟地址现在指向此新克隆的物理地址(该变量现在已更改)—一个过程被称为写时复制。

解决方法

为什么在两个printf之后%p的值相同,但是当我在子级中更改a的值时,它不会反映在父级上。打印%p时,它是指变量的虚拟地址吗?

在对象的虚拟地址周围移动会导致程序崩溃。他们将虚拟地址存储到变量中的对象。在fork之后,两个实例都具有具有相同布局的虚拟地址空间。

子进程的虚拟地址是否与父进程的虚拟地址相同(在对堆进行任何更改之前),或者新的子进程具有自己的虚拟地址,它们指向父进程的相同物理地址(只要因为没有对堆中的变量进行任何更改)?

我不明白这是什么有意义的区别。

我已经读到,对位于子堆上的变量进行更改时,将克隆物理内存,并且虚拟地址现在指向此新克隆的物理地址(该变量现在已更改)—一个过程被称为写时复制。

是的。这样避免了调用fork的进程已映射的每个页面的物理内存必须制作两个副本。

,

调用fork时,虚拟地址空间(以及文件描述符)被复制到新进程中。这意味着这两个过程在所有意图和目的上都是相同的。

现在,为了确保两个进程保持独立,所有物理内存均设为只读。尝试写入时,将引发处理器异常。内核将页面放入新页面,并从原始页面复制数据。它会重新运行该过程并允许写入。

为此,处理器必须具有将物理内存映射到虚拟空间的内存管理单元。这意味着未修改的Linux无法在微控制器单元上运行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。