Linux进程概念4程序地址空间-创新互联

一. 程序地址空间

此时我们的研究是在kernel 2.6.32和32位平台进行说明

成都创新互联成立与2013年,是专业互联网技术服务公司,拥有项目成都网站建设、成都网站设计网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元克什克腾做网站,已为上家服务,为克什克腾各地企业和个人服务,联系电话:189820811081. 程序地址空间图

我们在学习C/C++时候,应该学习过内存布局,以及了解各种变量的存储位置,例如局部变量存储在栈区,动态申请的内容在堆区,全局变量,常量等在数据常量区,如果用一张图来表示,如下:
在这里插入图片描述
已初始化区和未初始化区指全局变量

我们可以用代码来进行验证一下

#include#includeint g_unval;
int g_val = 100;
int main(int argc,char* argv[],char* env[])
{printf("代码区地址          :  %p\n",main);
    const char* p = "hello world!";
    printf("字符常量区地址      :  %p\n",p);
    printf("已初始化全局区地址  :  %p\n",&g_val);
    printf("未初始化全局区地址  :  %p\n",&g_unval);
    char* q0 = (char*)malloc(10);
    char* q1 = (char*)malloc(10);
    char* q2 = (char*)malloc(10);
    char* q3 = (char*)malloc(10);
    char* q4 = (char*)malloc(10);
    printf("堆区地址            :  %p\n",q0);
    printf("堆区地址            :  %p\n",q1);
    printf("堆区地址            :  %p\n",q2);
    printf("堆区地址            :  %p\n",q3);
    printf("堆区地址            :  %p\n",q4);
    printf("栈区地址            :  %p\n",&q0);
    printf("栈区地址            :  %p\n",&q1);
    printf("栈区地址            :  %p\n",&q2);
    printf("栈区地址            :  %p\n",&q3);
    printf("栈区地址            :  %p\n",&q4);
    printf("第一个命令行地址    :  %p\n",argv[0]);
    printf("最后一个命令行地址  :  %p\n",argv[argc-1]);
    printf("环境变量地址        :  %p\n",env[0]);
    return 0;
}

根据运行结果,发现从代码区开始到环境变量区,按照地址类型都是逐渐增大的,堆区向上生长,地址增大。栈区向下生长,地址减小
在这里插入图片描述

那么该程序地址空间图就是我们的内存空间吗,不是,我们可以证明以下:

当我们用fork创建一个子进程时,在程序中设置一个全局变量val=100
当我们分别用父子进程访问该全局变量时,在子进程中将该全局变量的值改为100
而我们再用父进程打印时,发现父进程打印的值还为100
并且父子进程打印该全局变量的地址都是一样的

所以父子进程访问的地址,绝对被保存到了不同的物理内存中

所以进程地址空间是内存吗?

进程地址空间不是内存,由上一步可知,内存中同一个地址的值,不可能被不同的进程读取,来表现出不同的值
所以进程地址空间绝对不是物理内存,我们在语言上打印出来的地址,其实都叫做“虚拟地址”。

**深入理解在这里插入图片描述
父子进程只能看到进程地址空间的虚拟内存
子进程会拷贝一份父进程的虚拟地址
也就是说:一个进程对应一份进程地址空间。有多少个进程就有多少个进程地址空间。

由上图可知,父子进程虽然虚拟地址一样,但其实子进程修改其值后,它两虚拟地址存储在物理内存中的地址将不一样。所以他们虚拟地址相同,但物理内存映射到不同地方

地址空间,是对物理内存的一种虚拟化表示,虚拟空间最后一定要以某种方式转化到物理内存
二. 物理内存

进程=管理维护进程的数据结构+进程代码数据
所以物理内存中存储了进程实际是存储了管理维护进程的数据结构和进程代码数据

1.假设没有虚拟地址空间

如果没有地址空间,我们进程访问的地址都是物理地址
此时会有很多问题。如:

  • 一个进程的数据存放的内存位置是不连续的。访问特别不方便
  • 增加了异常越界的概率。我们的指针容易写坏别人的空间和数据

在这里插入图片描述

页表中存储的是虚拟内存到物理内存的映射关系

尽管在内存中val1,val2两个不连续,但在虚拟地址中申请的为连续空间,通过映射关系将其与内存关联。
这个映射、关联由OS管理

这个时候从用户管理内存变为由OS管理内存,OS可以更好防止上面两个问题

总:

  • 地址空间,通过虚拟内存,将空间连续化处理了
  • 伪造的虚拟地址,可能并没有在该表存在。OS会帮我们终止,就没有写入内存
  • 在页表中,一个数据会有读写两个权限。
  • 页表管理映射关系

为什么要存在虚拟地址空间?

1.地址空间,通过虚拟内存,将空间连续化处理了
2.保护内存

系统中存在多个地址空间,需要被管理起来

2. 进程地址空间 什么是进程地址空间

地址空间本质是一个数据结构,用来描述进程所占有资源的一张表

struct mm_struct{......
}

我们每创建一个进程,便会创建一个mm_struct
在task_struct中有一部分空间指向进程地址空间
所以OS在管理进程时,同时也要将mm_struct组织与管理起来

地址空间如何工作?
  • 地址空间展现给用户的是一张虚拟地址表,当进程访问虚拟内存地址是,都需要通过页表转换去物理内存中拿到对应的数据和代码
  • 申请空间的本质:向内存索要空间,得到物理地址,然后在特定区域中申请没有使用的虚拟地址,建立映射关系,返回虚拟地址即可
注:
  • 物理地址用户都看不到,由OS管理
  • 用户编写的程序一般只映射到物理内存地址中的用户区,他们之间映射关系的页表,称之为用户级页表。还有一部分数据映射到物理内存地址中的内核中,我们称之为内核级页表
  • 计算机中的硬件mmu(内存管理单元),用于虚拟地址到物理地址的转换,这个转换不用跑CPU了,因该硬件帮做,提高效率

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


名称栏目:Linux进程概念4程序地址空间-创新互联
URL链接:http://ybzwz.com/article/heoig.html