LInux(三)程序地址空间、内存管理

目录

 一、程序地址空间

 二、内存管理方式

1、分段式内存管理

 2、分页式内存管理

3、段页式内存管理

 三、关于内存管理内容补充(分页式)

1、页表简单呈现

2、访问权限位

3、缺页中断

4.内存置换算法


一、程序地址空间

  创建父子进程同时访问同一变量,在子进程中对全局变量g_val进行修改

  1 #include                                                                          
  2 #include
  3 
  4 int g_val = 10;
  5 int main()
  6 {
  7     int ret = fork();
  8     if(ret<0){
  9       printf("error fork\n");
 10     }else if(ret==0){
 11       g_val = 300;
 12       printf("i am child, my g_val = %d,my &g_val = %p\n",g_val,&g_val);
 13     }else{
 14       printf("i am parent, my g_val = %d,my &g_val = %p\n",g_val, &g_val);
 15     }
 16     return 0;
 17 }

现象: 输出结果俩者不相同,但俩变量的地址相同。

 

LInux(三)程序地址空间、内存管理_第1张图片

程序地址空间:进程的虚拟地址空间

        系统为每一个程序运行通过mm_struct结构体(LInux下)所描述的一个虚拟的,连续的,完整的地址空间

        我们进程中访问内存时候看到的地址其实都是虚拟地址,经过页表映射之后得到物理地址进行进而访问物理内存

LInux(三)程序地址空间、内存管理_第2张图片

 进程并不直接访问物理地址,而是通过访问虚拟地址,进行映射访问物理地址的方式进行:

好处:

1、每个进程都有一个完整独立的虚拟地址空间,则地址可以随便使用,不同担心冲突

2、经过页表映射可以将数据存储在物理内存的任意位置,实现数据的离散式存储,提高内存利用率

3、在进行页表映射之后可以进行访问权限的控制

 二、内存管理方式

1、分段式内存管理

将一个整体的地址空间划分为多个段(代码段、数据段、堆区、栈……)

作用: 更加利于编译器对于地址的管理

俩个要素:段表,地址组成

        虚拟地址组成:段号,段内偏移量

        段表:一种数据结构,其中描述的信息,段号,物理内存的一个起始地址

LInux(三)程序地址空间、内存管理_第3张图片

通过段号找到段表项,得到一块物理内存的起始地址

屋里内存起始地址+偏移量就是实际数据存储位置

 2、分页式内存管理

将一个整体的地址空间划分为大量的小的分页page(当前一般默认都是4096字节为一页)

作用: 实现数据的离散存储,提高内存利用率

俩个关键要素:页表+虚拟地址组成

        页表:页号、物理内存块起始地址、缺页中断位、访问权限位……

        虚拟地址组成:页号+页内偏移

通过虚拟地址中的页号,在页表中找到对应的页表项,得到一个物理内存块的起始地址,加上页内偏移量就是实际的访问位置

二者不同的区别在于应用方向不同,分段式利于地址管理,分页式更加倾向于碎片化管理,提高内存利用率以及内存访问控制

3、段页式内存管理

先将地址空间进行分段,然后在每个分段内使用分页进行管理(集合了分段式与分页式的优势)

LInux(三)程序地址空间、内存管理_第4张图片

 三、关于内存管理内容补充(分页式)

1、页表简单呈现

LInux(三)程序地址空间、内存管理_第5张图片

 2、访问权限位

标记当前的地址能够进行什么操作

简单举例:

0号地址,也就是NULL,这个地址既不可读也不可写,因此一旦解引用或者修改则会内存访问错误

const修饰的常变量,具有常性,其实就是访问权限上只读

代码段的所有地址,都是只读的

3、缺页中断

当进程要访问一块内存时,经过页表映射的时候发现缺页中断位被置位(这个地址原先的数据现在不在内存中),则触发缺页中断

内存交换:

一个程序运行就要占据大量内存,但是物理内存是有限的,意味着内容总有耗尽时候

大佬们就有想法:按照某种规则将内存中的某些数据从内存中移出去,放到硬盘中存起来(放入swap分区)交换分区一般32G以内都是内存的俩倍

当我们访问数据的时候,刚好就是被移出去的数据时,就会触发缺页中断

触发缺页中断后,就需要重新进行内存置换,将数据从交换分区置换到内存中进行访问

4.内存置换算法

内存不够的时候,把哪些数据移出去放到交换分区上存储

        LRU--最久未使用                 LFU--最少未使用

操作系统中可以使用LRU(least recently used)内存淘汰旧数据的策略,如果内存需要加载新数据但空间又不足,则会按照最近访问时间进行排序,并将最老的数据淘汰,假设现在内存空间大小为6,原本内存中没有数据,对内存中数据的访问顺序如下: 1,2,5,3,4,6,1,4,3,6,7,8,3,9 则缺页次数为()

 LInux(三)程序地址空间、内存管理_第6张图片

LRU栈:当前引用不在栈中,且栈未满,放到栈顶;栈满,删除栈底,放到栈顶。当前引用在栈中,删除栈中原先位置,放到栈顶。

    缺页:当前引用不在页的某个帧中,即缺页。而LRU只是确定被置换的那个引用,即LRU栈底引用。

     前6次均缺页,因为每次的引用都不在已有的页中,缺页次数6,当前LRU栈:6->4->3->5->2->1

     第7次为1,在页中,不缺页,当前LRU栈:1->6->4->3->5->2

     第8次为4,在页中,不缺页,当前LRU栈:4->1->6->3->5->2

     第9次为3,在页中,不缺页,当前LRU栈:3->4->1->6->5->2

     第10次为6,在页中,不缺页,当前LRU栈:6->3->4->1->5->2

     第11次为7,不在页中,缺页。删除栈底2,将7放到栈顶。当前LRU栈:7->6->3->4->1->5

     第12次为8,不在页中,缺页。删除栈底5,将8放到栈顶。当前LRU栈:8->7->6->3->4->1

     第13次为3,在页中,不缺页。当前LRU栈:3->8->7->6->4->1

     第14次为9,不在页中,缺页。删除栈底1,将9放到栈顶。当前LRU栈:9->3->8->7->6->4

     综上,缺页9次。

你可能感兴趣的:(LInux,c++,c语言,开发语言)