内存管理之内存寻址

  • 内存管理是迄今为止Unix内核中最复杂的活动

    1. 虚拟内存: 所有新近的Unix系统都提供一种有用的抽象, 叫作虚拟内存(virtual memory);

      • 虚拟内存可以理解为一种逻辑层;
      • 处于应用程序的内存请求与硬件内存管理单元(Memory Management Unit, MMU)之间;
    2. 虚拟内存有很多用途和优点:
      • 若干个进程可以并发地执行, 每个进程通过虚拟内存就好像自己拥有整块内存一样;
      • 应用程序所需内存大于可用物理内存时也可以运行;
      • 程序只有部分代码装入内存时进程可以照样执行;
      • 允许每个进程访问可用物理内存的子集;
      • 进程可以共享库函数或者程序的一个单独内存映像;
      • 程序是可重定位的, 也就是说, 也就是说可以把程序放在物理内存的任何地方;
      • 程序员可以编写与机器无关的代码, 因为他们不必关心有关物理内存的组织结构;
        • 程序可重定位就可以直接是位置无关码;
    3. 虚拟内存子系统的主要成分是虚拟地址空间(virtual address space)的概念;
      • 进程所使用的一组内存不等同于物理内存地址;
      • 当进程使用一个虚拟地址时, 内核和MMU协同定位其在内存中的实际物理位置;
      • 现在有些CPU包含了能自动把虚拟地址转换为物理地址的硬件电路;
        • 把RAM(随机存取存储器 -- random access memory,RAM内存), 分为长度为4KB或8KB的页框(page frame);
        • 利用一个页表来制定虚拟地址到物理地址之间的对应关系;
        • 一块连续的虚拟地址请求可以通过分配一组非连续的物理地址页框而得到满足;
    4. 随机访问存储器(RAM)即内存的使用
      • Unix操作系统都将RAM分为两部分: 用于存放内核映像(内核代码和内核静态数据结构), RAM的其余部分由虚拟内存来处理;
      • 虚拟内存的管理分为三种情况:
        • 满足内核对缓冲区、描述符及其他动态内核数据结构的请求;
        • 满足进程对一般内存区的请求即对文件内存映射的请求;
        • 借助高速缓存从磁盘及其缓冲设备获得较好的性能;
      • 当可用内存达到临界时, 可以调用页框回收(page-frame-reclaiming)算法释放其他内存
      • 虚拟内存必须要解决的一个问题是内存碎片(因为虚拟内存支持不连续的物理内存, 不连续的物理内存可能造成内存碎片问题)
        • 还有一些内存空间, 但没有一块很大的连续内存, 照样会分配失败;
    5. 内核内存分配器(kernel memory allocator, KMA)
      • 它试图满足系统中所有部分对内存的请求;

        • 内核需要的内存;
        • 用户程序的系统调用, 用来增加用户进程的地址空间;
      • 一个好的KMA应该具有的特点:
        • 必须快(包括中断处理程序调用);
        • 必须把程序的浪费减到最小;
        • 必须努力减轻内存的碎片(fragmentation)问题;
        • 必须能与其他内存管理子系统合作, 以便借用和释放页框;
      • 几种不同的KMA算法:
        • 资源图分配算法(allocator);
        • 2的幂次方空闲链表;
        • McKusick-Karels分配算法
        • 伙伴系统(buddy系统)
        • Mach的区域(zone)分配算法
        • Dynix分配算法
        • solaris的slab分配算法
        • Linux的KMA在伙伴(buddy)系统之上采用slab分配算法
    6. 进程虚拟地址空间处理
      • 进程虚拟地址空间包括进程可以引用的所有虚拟内存地址;
      • 内核通常用一组内存区描述进程虚拟地址空间;
      • 当进程通过exec系统调用开始某个程序时, 内核分配给进程的虚拟地址空间由以下内存区组成:
        • 程序的执行代码
        • 程序的初始化数据
        • 程序的未初始化数据
        • 初始程序栈(即用户态栈)
        • 所需共享库的可执行代码和数据
        • 堆(由程序动态请求的内存)
      • 现代的Unix操作系统都采用了所谓的请求调页(demand paging)的内存分配策略;
        • 有了请求调页, 进程可以在他的页还没有在内存时就开始自行;
        • 当进程访问一个不存在的页时, MMU产生一个异常;
        • 异常处理程序找到受影响的内存区, 分配一个空闲的页, 并用适当的数据把它初始化;
        • 进程调用malloc或brk系统调用动态地请求内存时, 内核仅仅修改进程的堆内存区大小;
        • 只有师徒引用进程的虚拟内存地址而产生异常时, 才给进程分配页框(物理内存);
      • 虚拟内存也是采用了一些有效的策略: 写时复制策略;
        • 当一个新进程被创建时, 内核仅仅把父进程的页框赋给子进程的地址空间, 但是页框标记为只读, 一旦父子进程试图修改页中的内容时, 就会产生一个异常;
        • 异常处理程序再把再把新页框赋给受影响的进程, 并用原来页中的内容初始化新页框;
    7. 高速缓存
      • 物理内存的一大又是就是用作磁盘和其他块设备的高速缓存;

        • 尽可能的延时写磁盘的时间, 因此, 从磁盘读入内存的数据即使任何进程都不再使用它们, 它们也继续留在RAM中;
        • 前提条件: 新进程请求从磁盘中读或写的数据, 就是撤销进程曾拥有的数据;
        • 当一个进程访问齿盘式, 内核首先检查进程请求的数据是否在缓存中, 如果在(缓存命中), 内核就可以为进程请求提供服务而不访问磁盘;
      • sync系统调用把所有脏的缓冲区写入磁盘来轻质磁盘同步;
      • 为了避免数据丢失, 所有的操作系统都会注意周期性地把脏缓冲区写回磁盘;
    8. 设备驱动程序
      • 内核通过设备驱动程序(device driver) 与 I/O设备交互;
      • 设备驱动程序包含在内核中, 由一个或多个设备的数据结构和函数组成;
      • 包含以下优点:
        • 可以把特定设备的代码封装在特定的模块中;
        • 厂商可以在不了解内核源码而只知道接口规范的情况下, 就能增加新的设备;
        • 内核以统一的方式对待所有的设备, 并且通过相同的接口访问这些设备;
        • 可以把设备驱动程序写成模块, 并动态地把它们装进内核而不需要重新启动系统, 不需要时, 也可以动态地卸载模块, 以减少存储在RAM中的内核映像的大小;
      • 每个设备文件都有专门的设备驱动程序, 他们由内核调用以执行对硬件设备的请求操作;
      • Linux对帧缓冲提供一种抽象;

Linux内核初探的更多相关文章

  1. Linux内核初探 之 进程(三) —— 进程调度算法

    一.基本概念 抢占 Linux提供抢占式多任务,基于时间片和优先级对进程进行强制挂起 非抢占的系统需要进程自己让步(yielding) 进程类型 IO消耗型 经常处于可运行态,等待IO操作过程会阻塞 ...

  2. 初探Linux内核中的内存管理

    Linux内核设计与实现之内存管理的读书笔记 初探Linux内核管理 内核本身不像用户空间那样奢侈的使用内存; 内核不支持简单快捷的内存分配机制, 用户空间支持? 这种简单快捷的内存分配机制是什么呢? ...

  3. 初探linux内核编程,参数传递以及模块间函数调用

    一.前言                                  我们一起从3个小例子来体验一下linux内核编程.如下: 1.内核编程之hello world 2.模块参数传递 3.模块间 ...

  4. linux 内核与用户空间通信机制netlink初探

      1.Linux进程概述 Linux中的进程间通信机制源自于Unix平台上的进程通信机制.Unix的两大分支AT&T Unix和BSD Unix在进程通信实现机制上各有所不同,前者形成了运行 ...

  5. 初探内核之《Linux内核设计与实现》笔记下

    定时器和时间管理 系统中有很多与时间相关的程序(比如定期执行的任务,某一时间执行的任务,推迟一段时间执行的任务),因此,时间的管理对于linux来说非常重要. 主要内容: 系统时间 定时器 定时器相关 ...

  6. 初探内核之《Linux内核设计与实现》笔记上

    内核简介  本篇简单介绍内核相关的基本概念. 主要内容: 单内核和微内核 内核版本号 1. 单内核和微内核   原理 优势 劣势 单内核 整个内核都在一个大内核地址空间上运行. 1. 简单.2. 高效 ...

  7. 读《Linux内核设计与实现》我想到了这些书

          从题目中可以看到,这篇文章是以我读<Linux内核设计与实现>而想到的其他我读过的书,所以,这篇文章的主要支撑点是<Linux内核>.       开始读这本书已经 ...

  8. Linux内核源码分析 day01——内存寻址

    前言 Linux内核源码分析 Antz系统编写已经开始了内核部分了,在编写时同时也参考学习一点Linux内核知识. 自制Antz操作系统 一个自制的操作系统,Antz .半图形化半命令式系统,同时嵌入 ...

  9. 阿里云Linux服务器初探

    阿里云Linux服务器初探 阿里云Linux服务器初探 因为钱包的关系,本人买了一个660元2年的1核1GB的小服务器(centos是Linux的发行版),在当初是用2核4GB(内存)的时候使用的是w ...

随机推荐

  1. SqlServer中的事务使用

    一.事务的概念和特点 事务(transaction)是恢复和并发控制的基本单位. 事务的特点 原子性:事务是一个工作单元,要都成功,要么的失败 例子:A付款给B,A余额-100,B余额+100,只能都 ...

  2. [JVM-1]Java运行时数据区域

    Java虚拟机(JVM)内部定义了程序在运行时需要使用到的内存区域 这些区域都有自己的用途,以及创建和销毁的时间.有些区域随着虚拟机进程的启动而存在,有的区域则依赖用户线程的启动和结束而销毁和建立. ...

  3. ruby数组操作方法汇总

    1.数组定义 arr1 = [] arr2 = Array.new arr3 = ['1','2','3'] 2.输出 print arr3,"\n" #123 puts arr3 ...

  4. HDU - 4578 Transformation(线段树区间修改)

    https://cn.vjudge.net/problem/HDU-4578 题意 4种操作,区间加,区间乘,区间变为一个数,求区间的和.平方和以及立方和. 分析 明显线段树,不过很麻烦..看kuan ...

  5. Shell编程(四)Shell变量

    1. 自定义变量(仅在当前shell生效) 1.1 定义变量 #!/usr/bin/bash ip=115.239.210.27 if ping -c1 $ip &>/dev/null ...

  6. 前端基础之JQuery - day15

    写在前面 上课第15天,打卡: 张国臂掖,以通西域: ########### # 课上简书 # ########## http://jquery.cuishifeng.cn/index.html JQ ...

  7. 细说java系列之反射

    什么是反射 反射机制允许在Java代码中获取被JVM加载的类信息,如:成员变量,方法,构造函数等. 在Java包java.lang.reflect下提供了获取类和对象反射信息的相关工具类和接口,如:F ...

  8. C#窗口闪烁问题解决

    https://www.cnblogs.com/AndyDai/p/5203798.html 开发WinForm 程序时经常会遇到闪屏的问题,这会给用户造成很差的使用体验,所以必须妥善解决好这个问题. ...

  9. Docker 容器启动 查看容器状态 - 四

    1.容器两种方式进行启动 一种是基于创建一个容器并启动 docker create docker start 另一种 使用 run 创建自动启动:是状态下的停止 启动 docker start ngi ...

  10. react 在IE9下input标签使用e.target.value取值失败

    在react项目开发中,input标签使用onChange方法获取输入值改变state: <input type="text" id="redeemNum" ...