Linux内核学习--内存管理模块

  首先,Linux内核主要由五个部分组成,他们分别是:进程调度模块、内存管理模块、文件系统模块、进程间通信模块和网络接口模块。

本部分所讲的内存是内存管理模块,其主要的作用是有以下几点:

  1:内存管理模块还支持虚拟内存的管理方式,使得Linux支持的进程使用比实际的内存空间有更多的内存容量。

  2:保证所有的进程都能够安全的共享机器的主内存区;

  3:利用文件系统把暂时不用的内存数据转移到外部存储设备上去,需要的时候交换回来。

  我们在下面的叙述中逐条的剖析Linux是如何完成上面的工作的。

  首先,我们能够使用的地址空间要比实际的空间地址大小要大的多。我们首先认识几个概念:

  虚拟地址:直接又程序产生的地址空间,由段选择符(说白了就是说在哪一个段上)和段内偏移量组成;

  逻辑地址:由程序产生的,与段相关的偏移地址。应用程序员可以与逻辑地址打交道,但是分段和分页对他们来说是完全透明的;

  线性地址:是由虚拟地址到物理地址的中间层,是处理器可寻址的内存空间,程序代码产生的段选择符(可以知道其段的基址)然后加上段内偏移量就是其线性地址。如果启用了分页机制,那么线性地址要在经过变换变成物理地址,如果没有启用分页机制,那么他的线性地址就是物理地址(Intel 80386 线性地址为4G)。

  物理地址:是指出现在CPU外部总线上的寻找物理内存的地址信号,是最终的地址。

  虚拟内存:是指计算机所呈现出来的内存量远大于他的实际拥有的内存空间大小。

  内存—分段实现机制:

  在内存分段机制中,一个程序的逻辑地址通过分段机制自动映射到中间层的4G的线性地址中。程序每次的引用都是对内存段的中内存的引用。当程序进行引用时,其地址就是计算好的物理地址。

  但是,我们经过计算得到的物理地址,可能是一块根本就不存在的内存区域(内存的页表中标识出相应的页面不在内存中),当一个进程引用这样的一个地址的时候,就是发生缺页中断,并将引起中断的线性地址放入到CR2寄存器中。因此在处理中断的时候,就能够从寄存器中得到该页面的确定地址,这样就可以将页面从二级存储空间中(比如硬盘上)加载到物理内存中。如果此时物理内存已经被全部占用,那么可以借助二级存储空间的一部分作为交换区(这就是在安装Linux的时候预留的swap区域的作用),将一部分不使用的页面放入到交换区中,然后将要求的页面放入内存。

  在Linux 0.11系统中,内核设置设置全局描述符表GDT中的段描述符项数最大为256,其中两项空闲,两项系统使用,每个进程使用两项。因此系统最多容纳(256-2)/2 个任务,并且虚拟地址的范围126*64MB约等于8G,但是0.11内核中人工定义的任务数量为64个,每个任务逻辑地址范围为64MB,各个任务地址的起始地址为任务号码*64MB,因此全部任务使用的地址空间约为4GB。图中显示的是有四个任务的情况,内核的代码段和数据段被映射到内存开始16MB的部分,并且代码和数据在一个区域,完全相互重叠。第一个任务(任务0)比较特别,它是由内核启动,他的代码和数据包含在内核的代码和数据中,他的代码和数据段是从0-640KB的区域,其代码段与数据段也是完全重叠,并且与内核的代码数据段有重叠的部分。

进程0与进程1:

在这里大家可能会对进程0和进程1存在疑问,为什么这两个进程和别的进程是不一样的,在这里简单的对其进行介绍,在以后的学习中,会相信的分析。

进程0的介绍:

1. 进程0是所有其他进程的祖先, 也称作idle进程或swapper进程.

2. 进程0是在系统初始化时由kernel自身从无到有创建.

3. 进程0的数据成员大部分是静态定义的,即由预先定义好的INIT_TASK, INIT_MM等宏初始化.

进程0的描述符init_task定义在arch/arm/kernel/init_task.c,由INIT_TASK宏初始化。 init_mm等结构体定义在include/linux/init_task.h内,为init_task成员的初始值,分别由对应的初始化宏如INIT_MM等初始化

进程1的介绍:

进程0最终会通过调用kernel_thread创建一个内核线程去执行init函数,这个新创建的内核线程即Process 1(这时还是共享着内核线程0的资源属性如地址空间等)。init函数继续完成剩余的内核初始化,并在函数的最后调用execve系统调用装入用户空间的可执行程序/sbin/init,这时进程1就拥有了自己的属性资源,成为一个普通进程(init进程)。至此,内核初始化和启动过程结束。下面就进入了用户空间的初始化,最后运行shell登陆界面。(注:Init进程一直存活,因为它创建和监控在操作系统外层执行的所有进程的活动。)

  在实际写代码的过程中,我们经常使用动态的对内存进行分配和回收,比如malloc和free(new与delete的底层实现也是malloc和free),那么Linux是怎么样进行管理的呢?

  首先要说明的一点就是,我们所申请的内存容量和大小是由高层次的C函数进行管理,内核本身无权进行插手管理,因为内核已经为每个进程分配了64M的线性空间,所以进程的寻址空间只是在他的64M的空间中进行寻址。

  但是内核在这中间并不是无所作为的,内核会为进程使用的代码和数据空间维护一个当前位置值brk,这个值保存在每个进程的数据结构中。他指出进程代码和数据(包括动态分配的数据空间)在进程地址中末端的位置,当malloc函数为程序分配内存时候,他会调用brk()把程序新增长的长度通知内核,然后内核代码更新进程数据结构中的brk值,但是,这个时候并不为新申请的空间映射物理内存页面。只有当程序寻找不存在的物理地址的时候,内核才会进行相应的物理地址映射工作。(当进程代码寻找的某个页面不存在,并且该页面处于某个进程堆的范围内,那么CPU产生一个缺页异常,建立映射关系)。

  上面所说的就是解释的Linux内存管理的第一个功能,下面主要解释一下Linux是如何保证所有的进程都能够安全的共享机器的主内存区。

  首先Intel 80X86的CPU有四个保护级别,0具有最高的保护级别,而3的级别最低。Linux适用0和3两个保护级别。内核的代码和数据本身会由系统中所有的进程共享,因此他保存在全局地址空间中。而每个任务进程有着自己的局部地址空间。每个进程的地址空间是别的任务看不到的。

  当一个任务记性系统调用而陷入内核代码执行中,我们就称进程进入到内核运行态。此时处理器处于特权级别最高的0级内核代码的执行中。当进程处于内核态的时候执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程执行用户自己的代码时,则称其为用户运行态,即此时的处理器在特权3上。当用户执行程序突然被中断程序中断的时候,此时用户程序也可以象征性的称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。用户态与内核态将在后面进行详细的分析。

posted on 2015-04-23 17:14 MPoooooo 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/MPoooooo/p/4451138.html

Linux内核学习--内存管理模块相关推荐

  1. linux内核之内存管理.doc,linux内核之内存管理.doc

    Linux内核之内存管理 作者:harvey wang 邮箱:harvey.perfect@ 新浪博客地址:/harveyperfect ,有关于减肥和学习英语相关的博文,欢迎交流 把linux内存管 ...

  2. fork的黑科技,它到底做了个啥,源码级分析linux内核的内存管理

    最近一直在学习linux内核源码,总结一下 https://github.com/xiaozhang8tuo/linux-kernel-0.11 一份带注释的源码,学习用. fork的黑科技,它到底做 ...

  3. Linux内核笔记--内存管理之用户态进程内存分配

    内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...

  4. linux 内核学习11-内核模块参数

    linux 内核学习11-内核模块参数 内核模块作为一个可拓展的动态模块,为Linux内核提供灵活性,所以需要依据不同的场景来传递不同的参数,实现不同的功能 1. 准备工作 #define modul ...

  5. Linux内核中内存管理相关配置项的详细解析3

    接前一篇文章:Linux内核中内存管理相关配置项的详细解析2 5. 2:1 compression allocator (zbud) 对应配置变量为:CONFIG_ZBUD. 此项默认为选中(如果前一 ...

  6. 从底层原理出发,了解Linux内核之内存管理

    本文讲解更加底层,基本都是从Linux内核出发,会更深入.所以当你都读完,然后再次审视这些功能的实现和设计时,我相信你会有种豁然开朗的感觉. 1.页 内核把物理页作为内存管理的基本单元. 尽管处理器的 ...

  7. 通过fork来剖析Linux内核的内存管理和进程管理(下)

    上一篇文章我们讲到fork的时候内存管理相关的内容,时间大概隔了快一周了,发布下篇文章,写文章确实费时费力,需要仔细推敲,原创不易,希望大家多多支持吧.本文讲解fork的时候进程管理相关的内容,主要讲 ...

  8. 通过fork来剖析Linux内核的内存管理和进程管理(上)

    1.开场白 本文主要从内存管理和进程管理两个维度来窥探一下fork背后隐藏的技术细节,希望能够通过本文让大家站在一个高度去看进程创建. 全文分为两部分讲解:fork的内存管理部分和进程管理部分,内存管 ...

  9. 【Linux内核】内存管理——内存回收机制

    转载请注明: https://www.cnblogs.com/Ethan-Code/p/16626560.html 内存回收的方式 前文提到malloc的内存分配方式,malloc申请的是虚拟内存,只 ...

最新文章

  1. python函数的定义域_python中多线程的变量定义域问题
  2. php嵌入html后缀_php中怎么嵌入html代码
  3. android handler 主线程吗,[android开发]非主线程进行handler操作
  4. 快来领猪肉啊,网易云官网建设意见征集计划获奖名单公布
  5. oracle过滤器基础,Oracle培训(四十六)——Servlet第六章知识点总结——过滤器编程...
  6. Web安全学习week6
  7. ClassLoader简介
  8. 【DP】和谐的奶牛(jzoj 1750)
  9. String类的编码和解码问题
  10. 拓端tecdat|使用R语言进行机制检测的隐马尔可夫模型HMM
  11. javascript滚动条响应鼠标滑轮的实现上下滚动事件
  12. LFW database
  13. Wcf 文件上传下载
  14. markdown设置字体颜色、大小、背景
  15. 游戏金币数据库:QPTreasureDB
  16. 条件if语句的多种写法
  17. 获取android 默认的机器人图标,APP桌面只显示默认机器人图标的几个解决方法
  18. 2009年具有高等学历教育招生资格普通本科高职院校名单
  19. TCL加码半导体,能走好显示面板国产化最后一段路吗?
  20. Windows 文件共享

热门文章

  1. 遍历系统中所有的进程,可根据名字或ID查找某一个线程
  2. [转发]R语言数据挖掘实践——使用party包构建决策树
  3. react+webpack 引入字体图标
  4. Win7如何改变用户文件夹位置
  5. 20145202马超 《Java程序设计》第六周学习总结
  6. Graphite在centeros 6下安装
  7. 在Centos 6.5 上面配置 SVN
  8. [游戏模版15] Win32 飞机射击
  9. [业界资讯]腾讯QQ同时在线用户数突破8000万
  10. 开机f8修复电脑步骤_电脑维修实战,修复电脑开机的各种报错提示,看了不后悔...