进程地址空间

2019-07-14 10:27发布

class="markdown_views prism-dracula">

进程的地址空间

背景
  • Linux32位操作系统
  • 内核版本:Linux version 2.6.32-754.3.5.el6.i686
Linux可执行程序文件空间布局 这里写图片描述 查看文件结构命令 size + 可执行文件名 size - list section sizes and total size. The GNU size utility lists the section sizes---and the total size---for each of the object or archive files objfile in its argument list. By default, one line of output is generated for each object file or each module in an archive. objfile... are the object files to be examined. If none are specified, the file "a.out" will be used. [liu@localhost 02]$ ls env env.c getenv getenv.c orphan orphan.c [liu@localhost 02]$ size env text data bss dec hex filename 1195 252 12 1459 5b3 env [liu@localhost 02]$ Linux进程空间结构
这里写图片描述 关于Linux进程空间结构
在进程第一篇博客提到:fork()会创建一个子进程,会复制父进程的所有资源,但是会拥有和父进程相独立的数据资源与代码区关于fork创建独立空间,以及程序证明的例子 既然创建了独立空间,那么来探究一下对于同一变量在父进程与子进程的地址显示为多少? #include #include int _val = 100; int main(void) { pid_t pid = fork(); if(pid < 0) perror("fork : "), exit(0); else if(pid == 0) { printf("this is child _val : %d and it's addr : %p ", _val, &_val); } else { printf("this is parent _val : %d and it's addr : %p ", _val, &_val); } return 0; } 输出结果 : [liu@localhost jcaddr]$ ./addr this is parent _val : 100 and it's addr : 0x80497b4 this is child _val : 100 and it's addr : 0x80497b4 改变一下: [liu@localhost jcaddr]$ cat addr.c #include #include int _val = 100; int main(void) { pid_t pid = fork(); if(pid < 0) perror("fork : "), exit(0); else if(pid == 0) { _val = 200; printf("this is child _val : %d and it's addr : %p ", _val, &_val); } else { _val = 50; printf("this is parent _val : %d and it's addr : %p ", _val, &_val); } return 0; } 输出结果 [liu@localhost jcaddr]$ ./addr this is parent _val : 50 and it's addr : 0x80497c4 this is child _val : 200 and it's addr : 0x80497c4 发现进程之间的变量确实是空间独立的,但是这两个进程的变量却是一样的。这样就引出了虚拟内存的概念。
早期的内存分派方式
这里写图片描述
缺点:降低了效率,处理速度慢,难维护,产生了很多不必要的内存浪费。
分段
1.在编码的过程中,只要指名了所属段,代码和数据段中出现的所有地址都从0x00000000开始,映射关系完全由操作系统维护。
2.cpu将内存分割位不同的段,于是指令和数据的有效地址斌不是真正的物理地址二十相对于段首地址的偏移地址。 这里写图片描述 缺点:
  • 分段之后,每个进程可能会剩余空间,虽然加快了处理速度,但是浪费了内存。

分段+虚拟地址空间 PCB中的一部分信息就是保存程序的地址空间(mm_struct),同过页表的映射到具体的物理空间,期间程序在物理内存被分段加载内存。
这里写图片描述
关于虚拟内存大小: ·在mm_struct上,都显示为物理内存的大小,这一点可以想到 {MOD}的1T容可能人们单独用不了1T,所以一百个人可能硬盘10T就ok
关于Linux下的写时拷贝思想 ·在fork创建子进程时,子进程复制整个父进程的PCB,包括页表在内,在对子进程中的数据进行操作的时候,页表才开辟新的物理内存,这一点可以类比C++中的写时拷贝
关于页表
·页表既可以将虚拟内存映射到物理内存,也维护着许多,包含有访问权限等等许多内容