自学内容网 自学内容网

进程地址空间

概念

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main()
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        return 0;
    }
    else if(id == 0)
    {
        //child
        printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
    }
    else
    {
        //parent
        printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
    }
    sleep(1);
    return 0;
}

父子进程输出的地址是一致的,但是变量内容不一样。

变量内容不一样,所以父子进程输出的变量绝对不是同一个变量。但是地址值是一样的,说明该地址绝对不是物理地址。

  • 在Linux地址下这种地址叫做虚拟地址。
  • 我们在用C、C++语言所看到的地址全部都是虚拟地址。
  • 物理地址用户一概看不到,是由操作系统管理。操作系统必须负责将虚拟地址转化为物理地址。

进程地址空间是指进程可用于寻址内存的一套地址集合。它是一个抽象概念,为进程提供了一种独立于物理内存的、连续的内存视图。

组成部分

同一个变量地址相同,其实就是虚拟地址相同,内容不同,其实就是被映射到了不同的物理地址。

  • 代码段:存放程序的可执行代码,通常是只读的,以防止程序运行时修改自身代码。
  • 数据段:包含全局变量和静态变量。其中,初始化的全局变量和静态变量存放在数据段的初始化部分,未初始化的存放在数据段的未初始化部分(.bss段)。
  • 堆:用于动态分配内存,进程可以在运行期间使用函数(如C语言中的malloc)在堆上申请内存空间,其大小可以动态增长,向上扩展。
  • 栈:用于存储局部变量、函数参数和函数调用的返回地址等。栈的生长方向是向下的,随着函数调用和局部变量的分配而动态变化。

与物理内存的关系

  • 进程地址空间通过页表等机制映射到物理内存。在现代操作系统中,进程地址空间往往比物理内存大,操作系统通过内存管理技术(如虚拟内存技术)实现进程地址空间到物理内存的映射,允许将暂时不使用的页面置换到磁盘等外部存储设备上。
  • 子进程在创建的时候通常会继承父进程的地址空间结构,包括代码段,数据段的布局。
  • 子进程有自己的独立的虚拟地址空间,其虚拟地址的范围和布局进程,地质空间的结构相对应。
  • 但是当子进程发生修数据修改时,子进程使用自己的虚拟地址进行操作。
  • 首先通过虚拟地址找到相应的页表项。
  • 如果该数据所在的页已经在物理内存中,且有对应的页表,但是与父进程指向同一个物理地址,那么操作系统会发生写时拷贝。
  • 子进程重新映射虚拟地址页表。到物理地址之间的关系。
  • 在用户层面上,修改前后的子进程数据的虚拟地址是一致的。
  • 但是在底层页表映射的物理物理地址是不一致的。

原文地址:https://blog.csdn.net/2301_78131481/article/details/142716810

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!