精华内容
下载资源
问答
  • 内存分配策略分配方法

    千次阅读 2018-04-23 16:29:15
    点击打开链接----- 在为进程分配内存时,将涉及到3个问题:1)最小物理块数确定;...-- 进程应获得最少物理块数与计算机硬件结构有关,取决于指令格式、功能和寻址方式。2、物理分配策略-- 在...

    点击打开链接

    ----- 在为进程分配内存时,将涉及到3个问题:

    1)最小物理块数的确定;2)物理块的分配策略;3)物理块的分配算法

    1、最小物理块数的确定

    -- 这里所说的最小物理块数,是指能保证进程正常运行所需的最小物理块数。

    -- 当系统为进程分配的物理块数小于此值时,进程将无法运行。

    -- 进程应获得的最少物理块数与计算机的硬件结构有关,取决于指令的格式、功能和寻址方式

    2、物理块的分配策略

    -- 在请求分页系统中,可采取两种内存分配策略,即固定可变分配策略。在进行置换时,也可采取两种策略,即全局置换局部置换

       于是可组合出以下三种适用的策略。

    1)固定分配局部置换(Fixed Allocation,Local Replacement)

    ---- 这是指基于进程的类型(交互型或批处理型等),或根据程序员、程序管理员的建议,为每个进程分配一定数目的物理块,在整个运行期间

    不再改变。采用该策略时,如果进程在运行中发现缺页,则只能从该进程在内存的n个页面中选出一个页换出,然后再调入一页,以保证分配给该

    进程的内存空间不变(固定分配)。

    ---- 实现这种策略的困难在于:应为每个进程分配多少个物理块难以确定。若太少,会频繁地出现缺页中断,降低了系统的吞吐量;若太多,又必

    然使内存中驻留的进程数目减少,进而可能造成CPU空闲或其他资源空闲的情况,而且在实现进程对换时,会花费更多的时间。

    2)可变分配全局置换(Variable Allocation,Global Replacement)

    这可能是最易于实现的一种物理块分配和置换策略,已用于若干个OS中。在采用这种策略时,先为系统中的每个进程分配一定数目的物理块,而

    OS自身也保持一个空闲物理块队列。当某进程发现缺页时,由系统从空闲物理块队列中取出一个物理块分配给该进程,并将欲调入的(缺)页装

    入其中。这样,凡产生缺页(中断)的进程,都将获得新的物理块。仅当空闲物理块队列中的物理块用完时,OS才能从内存中选择一页调出,该页

    可能是系统中任一进程的页,这样,自然又会使那个进程的物理块减少,进而使其缺页率增加。

    3)可变分配局部置换(Variable Allocation,Local Replacement)

    这同样是基于进程的类型或根据程序员的要求,为每个进程分配一定数目的物理块,但当某进程发现缺页时,只允许从该进程在内存的页面中选出

    一页换出,这样就不会影响其它进程的运行。如果进程在运行中频繁地发生缺页中断,则系统需再为该进程分配若干个附加的物理块,直至该进程

    的缺页率减少到适当程度为止;反之,若一个进程在运行过程中的缺页率特别低,则此时可适当减少分配给该进程的物理块数,但不应引起其缺页率

    的明显增加。

    ---- 全局是指置换页面时,换出的页面可能是内存中的任一进程的页面,局部只能是本(缺页)进程的页面。

    ---- 固定分配指为一个进程分配的物理块是固定的,可变分配指可根据缺页率调整所分配的物理块数。

    3、物理块分配算法

    -- 在采用固定分配策略时,如何将系统中可供分配的所有物理块分配给各个进程,可采用下述几种算法。

    1)平均分配算法

    -- 这是将系统中所有可供分配的物理块平均分配给各个进程。例如,当系统中有100个物理块,有5个进程在运行时,每个进程可分得20个物理块。

    这种方法看似公平,实际不然,因为它未考虑到各进程本身的大小

    假如有一个进程大小为200页,只分配给它20个块,它必然有很高的缺页率;而另一进程只有10页,却有10个物理块闲置未用。

    2)按比例分配算法

    -- 这是根据进程的大小按比例分配物理块的算法。如果系统中共有n个进程,每个进程的页面数为Si,则系统中各进程页面数的总和为:

        S=S1+S2+...+Si+...+Sn-1+Sn (i=1~n)     又假定系统中可用的物理块总数为m,则每个进程所能分到的物理块数为bi,则有:

        bi=(Si*m)/S   其中,b应该取整,它必须大于最小物理块数。

    3)考虑优先权的分配算法

    -- 在实际应用中,为了照顾到重要的、紧迫的作业能尽快地完成,应为它分配较多的内存空间。通常采取的方法是把内存中可供分配的所有物理块

    分成两部分:一部分按比例地分配给各进程;另一部分则根据各进程的优先权,适当地增加其相应份额后,分配给各进程。

    在有的系统中,如重要的实时控制系统,则可能是完全按优先权来为各进程分配其物理块的。

    4、调页策略

    ---- 预调页策略和请求调页策略

    ---- 确定从何处调入页面

    请求分页系统中的外存分为两部分:文件区对换区(用于存放文件的文件区和用于存放对换页面的对换区)。

    通常,对换区采用连续分配方式,文件区是采用离散分配方式。故对换区的磁盘I/O速度比文件区的高。何处调入分3种情况:

    -- 1)系统拥有足够的对换区空间,可全部从对换区调入所需页面。在进程运行前,需将与该进程有关的文件从文件区拷贝到对换区。

    -- 2)系统缺少足够的对换区空间,不会被修改的文件都直接从文件区调入,当换出这些页面时,由于它们未被修改而不必将它们换出,以后

    再调入时,仍从文件区直接调入。对于那些可能被修改的部分,在将它们换出时,需调到对换区,以后需要从对换区调入。

    -- 3)Unix方式。凡是未运行过的页面,都应从文件区调入。曾经运行过但又被换出的页面,放在对换区,调入时从对换区调入。Unix系统运行

    页面共享,因此某进程所请求的页面有可能已被其它进程调入内存,此时无需再从对换区调入。

    展开全文
  • 重点内容:☆ linux 内存组织结构和页面布局,内存碎片产生原因和优化算法。☆linux 内核几种内存管理的方法,内存使用场景以及内存使用的那些坑。☆从内存的原理和结构,到内存的算法优化,再到使用场景,去探寻...

    97c4e3b662de6b85a8ac8e7349f34960.png

    重点内容:

    ☆ linux 内存组织结构和页面布局,内存碎片产生原因和优化算法。

    ☆linux 内核几种内存管理的方法,内存使用场景以及内存使用的那些坑。

    ☆从内存的原理和结构,到内存的算法优化,再到使用场景,去探寻内存管理的机制和奥秘。

    1、内存是什么?

    1)内存又称主存,是 CPU 能直接寻址的存储空间,由半导体器件制成

    2)内存的特点是存取速率快

    658c5f7e8855c13c0359750c6d423750.png

    2、内存的作用

    1)暂时存放 cpu 的运算数据

    2)硬盘等外部存储器交换的数据

    3)保障 cpu 计算的稳定性和高性能

    c5ace2f89a11742e55d5857707afd988.png

    1、linux 内存地址空间 Linux 内存管理全貌

    8f3bccca4d2b8c40cb95d7c47c0bc26d.png

    2、内存地址—用户态&内核态

    ·用户态:Ring3 运行于用户态的代码则要受到处理器的诸多

    ·内核态:Ring0 在处理器的存储保护中,核心态

    ·用户态切换到内核态的 3 种方式:系统调用、异常、外设中断

    ·区别:每个进程都有完全属于自己的,独立的,不被干扰的内存空间;用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用;内核态线程共享内核地址空间。

    8239f063eb4a923355691e140018aceb.png

    3、内存地址—MMU 地址转换

    ·MMU 是一种硬件电路,它包含两个部件,一个是分段部件,一个是分页部件

    ·分段机制把一个逻辑地址转换为线性地址

    ·分页机制把一个线性地址转换为物理地址

    4543d887e5b9b1f12de0eb9d0b53dfd9.png

    4、内存地址——分段机制

    1) 段选择符

    ·为了方便快速检索段选择符,处理器提供了 6 个分段寄存器来缓存段选择符,它们是:cs,ss,ds,es,fs 和 gs

    ·段的基地址(Base Address):在线性地址空间中段的起始地址

    ·段的界限(Limit):在虚拟地址空间中,段内可以使用的最大偏移量

    2) 分段实现

    ·逻辑地址的段寄存器中的值提供段描述符,然后从段描述符中得到段基址和段界限,然后加上逻辑地址的偏移量,就得到了线性地址。

    44e2c653b55c5a1c2954518b8993a696.png

    5、内存地址—分页机制(32 位)

    ·分页机制是在分段机制之后进行的,它进一步将线性地址转换为物理地址

    ·10 位页目录,10 位页表项, 12 位页偏移地址

    ·单页的大小为 4KB

    649275a712a77f8773dfe95567da6a71.png

    6、用户态地址空间

    1ff7ce6901ab0441931e80a169ff2f5b.png

    ·TEXT:代码段可执行代码、字符串字面值、只读变量

    ·DATA:数据段,映射程序中已经初始化的全局变量

    ·BSS 段:存放程序中未初始化的全局变量

    ·HEAP:运行时的堆,在程序运行中使用 malloc 申请的内存区域

    ·MMAP:共享库及匿名文件的映射区域

    ·STACK:用户进程栈

    7、内核态地址空间

    3b83d0ed66b1b589dbf0e5f0eff6afe2.png

    ·直接映射区:线性空间中从 3G 开始最大 896M 的区间,为直接内存映射区

    ·动态内存映射区:该区域由内核函数 vmalloc 来分配

    ·永久内存映射区:该区域可访问高端内存

    ·固定映射区:该区域和 4G 的顶端只有 4k 的隔离带,其每个地址项都服务于特定的用途,如:ACPI_BASE 等

    8、进程内存空间

    ·用户进程通常情况只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址

    ·内核空间是由内核负责映射,不会跟着进程变化;内核空间地址有自己对应的页表,用户进程各自有不同额页表

    5039726459f2c205647fef76b0494fd7.png

    Linux 内存分配算法

    内存管理算法——对讨厌自己管理内存的人来说是天赐的礼物

    1、内存碎片

    1) 基本原理

    ·产生原因:内存分配较小,并且分配的这些小的内存生存周期又较长,反复申请后将产生内存碎片的出现

    ·优点:提高分配速度,便于内存管理,防止内存泄露

    ·缺点:大量的内存碎片会使系统缓慢,内存使用率低,浪费大

    2) 如何避免内存碎片

    ·少用动态内存分配的函数(尽量使用栈空间)

    ·分配内存和释放的内存尽量在同一个函数中

    ·尽量一次性申请较大的内存,而不要反复申请小内存

    ·尽可能申请大块的 2 的指数幂大小的内存空间

    ·外部碎片避免——伙伴系统算法

    ·内部碎片避免——slab 算法

    ·自己进行内存管理工作,设计内存池

    2、伙伴系统算法—组织结构

    1) 概念

    ·为内核提供了一种用于分配一组连续的页而建立的一种高效的分配策略,并有效的解决了外碎片问题

    ·分配的内存区是以页框为基本单位的

    2) 外部碎片

    ·外部碎片指的是还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域3) 组织结构

    ·把所有的空闲页分组为 11 个块链表,每个块链表分别包含大小为 1,2,4,8,16,32,64,128,256,512 和 1024 个连续页框的页块。最大可以申请 1024 个连续页,对应 4MB 大小的连续内存

    174a3f257cf5a4de1a2e0ff16473be21.png

    3、伙伴系统算法—申请和回收

    1) 申请算法

    ·申请 2^i 个页块存储空间,如果 2^i 对应的块链表有空闲页块,则分配给应用

    ·如果没有空闲页块,则查找 2^(i 1) 对应的块链表是否有空闲页块,如果有,则分配 2^i 块链表节点给应用,另外 2^i 块链表节点插入到 2^i 对应的块链表中

    ·如果 2^(i 1) 块链表中没有空闲页块,则重复步骤 2,直到找到有空闲页块的块链表

    ·如果仍然没有,则返回内存分配失败

    2) 回收算法

    ·释放 2^i 个页块存储空间,查找 2^i 个页块对应的块链表,是否有与其物理地址是连续的页块,如果没有,则无需合并

    befb7c9518a81e3b6164df441709f03e.png

    ·如果有,则合并成 2^(i 1)的页块,以此类推,继续查找下一级块链接,直到不能合并为止

    20fadcb94becec32767d7a1ecc5fba64.png

    3) 条件

    ·两个块具有相同的大小

    ·它们的物理地址是连续的

    ·页块大小相同

    4、如何分配 4M 以上内存?

    1) 为何限制大块内存分配

    ·分配的内存越大, 失败的可能性越大

    ·大块内存使用场景少

    2) 内核中获取 4M 以上大内存的方法

    ·修改 MAX_ORDER, 重新编译内核

    ·内核启动选型传递"mem="参数, 如"mem=80M,预留部分内存;然后通过

    ·request_mem_region 和 ioremap_nocache 将预留的内存映射到模块中。需要修改内核启动参数, 无需重新编译内核. 但这种方法不支持 x86 架构, 只支持 ARM, PowerPC 等非 x86 架构

    ·在start_kernel中mem_init 函数之前调用 alloc_boot_mem 函数预分配大块内存, 需要重新编译内核

    ·vmalloc 函数,内核代码使用它来分配在虚拟内存中连续但在物理内存中不一定连续的内存

    5、伙伴系统—反碎片机制

    1) 不可移动页

    ·这些页在内存中有固定的位置,不能够移动,也不可回收

    ·内核代码段,数据段,内核 kmalloc() 出来的内存,内核线程占用的内存等

    2) 可回收页

    ·这些页不能移动,但可以删除。内核在回收页占据了太多的内存时或者内存短缺时进行页面回收3) 可移动页

    ·这些页可以任意移动,用户空间应用程序使用的页都属于该类别。它们是通过页表映射的

    ·当它们移动到新的位置,页表项也会相应的更新

    6、slab 算法—基本原理

    1) 基本概念

    ·Linux 所使用的slab分配器的基础是Jeff Bonwick 为 SunOS 操作系统首次引入的一种算法

    ·它的基本思想是将内核中经常使用的对象放到高速缓存中,并且由系统保持为初始的可利用状态。比如进程描述符,内核中会频繁对此数据进行申请和释放

    2) 内部碎片

    ·已经被分配出去的的内存空间大于请求所需的内存空间

    3) 基本目标

    ·减少伙伴算法在分配小块连续内存时所产生的内部碎片

    ·将频繁使用的对象缓存起来,减少分配、初始化和释放对象的时间开销

    ·通过着色技术调整对象以更好的使用硬件高速缓存

    7、slab 分配器的结构

    ·由于对象是从 slab 中分配和释放的,因此单个 slab 可以在 slab 列表之间进行移动

    ·slabs_empty 列表中的 slab 是进行回收(reaping)的主要备选对象

    ·slab 还支持通用对象的初始化,从而避免了为同一目而对一个对象重复进行初始化

    328c224eb05bd8da1a09a3c27b57a0ff.png

    8、slab 高速缓存

    1) 普通高速缓存

    ·slab 分配器所提供的小块连续内存的分配是通过通用高速缓存实现的

    ·通用高速缓存所提供的对象具有几何分布的大小,范围为 32 到 131072 字节。

    ·内核中提供了 kmalloc() 和 kfree() 两个接口分别进行内存的申请和释放

    2) 专用高速缓存

    ·内核为专用高速缓存的申请和释放提供了一套完整的接口,根据所传入的参数为具体的对象分配 slab 缓存

    ·kmem_cache_create() 用于对一个指定的对象创建高速缓存。它从 cache_cache 普通高速缓存中为新的专有缓存分配一个高速缓存描述符,并把这个描述符插入到高速缓存描述符形成的 cache_chain 链表中

    ·kmem_cache_alloc() 在其参数所指定的高速缓存中分配一个 slab。相反, kmem_cache_free() 在其参数所指定的高速缓存中释放一个 slab

    9、内核态内存池

    1) 基本原理

    ·先申请分配一定数量的、大小相等(一般情况下) 的内存块留作备用

    ·当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存

    ·这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升

    2) 内核 API

    ·mempool_create 创建内存池对象

    ·mempool_alloc 分配函数获得该对象

    ·mempool_free 释放一个对象

    ·mempool_destroy 销毁内存池

    22b8b984dde0f7229b0b736ddde71de1.png

    10、用户态内存池

    1) C++ 实例

    82e810a6e807b5f8c4bf1eff7f43599b.png

    11、DMA 内存

    1) 什么是 DMA

    ·直接内存访问是一种硬件机制,它允许外围设备和主内存之间直接传输它们的 I/O 数据,而不需要系统处理器的参与2) DMA 控制器的功能

    ·能向 CPU 发出系统保持(HOLD)信号,提出总线接管请求

    ·当 CPU 发出允许接管信号后,负责对总线的控制,进入 DMA 方式

    ·能对存储器寻址及能修改地址指针,实现对内存的读写操作

    ·能决定本次 DMA 传送的字节数,判断 DMA 传送是否结束

    ·发出 DMA 结束信号,使 CPU 恢复正常工作状态

    2) DMA 信号

    ·DREQ:DMA 请求信号。是外设向 DMA 控制器提出要求,DMA 操作的申请信号

    ·DACK:DMA 响应信号。是 DMA 控制器向提出 DMA 请求的外设表示已收到请求和正进行处理的信号

    ·HRQ:DMA 控制器向 CPU 发出的信号,要求接管总线的请求信号。

    ·HLDA:CPU 向 DMA 控制器发出的信号,允许接管总线的应答信号

    ed69fba69919e4bfa189fa3cc07095e4.png

    内存使用场景

    out of memory 的时代过去了吗?no,内存再充足也不可任性使用。

    1、内存的使用场景

    ·page 管理

    ·slab(kmalloc、内存池)

    ·用户态内存使用(malloc、relloc 文件映射、共享内存)

    ·程序的内存 map(栈、堆、code、data)

    ·内核和用户态的数据传递(copy_from_user、copy_to_user)

    ·内存映射(硬件寄存器、保留内存)

    ·DMA 内存

    2、用户态内存分配函数

    ·alloca 是向栈申请内存,因此无需释放

    ·malloc 所分配的内存空间未被初始化,使用 malloc() 函数的程序开始时(内存空间还没有被重新分配) 能正常运行,但经过一段时间后(内存空间已被重新分配) 可能会出现问题

    ·calloc 会将所分配的内存空间中的每一位都初始化为零

    ·realloc 扩展现有内存空间大小

    a) 如果当前连续内存块足够 realloc 的话,只是将 p 所指向的空间扩大,并返回 p 的指针地址。这个时候 q 和 p 指向的地址是一样的

    b) 如果当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p 指向的内容 copy 到 q,返回 q。并将 p 所指向的内存空间删除

    3、内核态内存分配函数

    函数分配原理最大内存其他_get_free_pages直接对页框进行操作4MB适用于分配较大量的连续物理内存kmem_cache_alloc基于 slab 机制实现128KB适合需要频繁申请释放相同大小内存块时使用kmalloc基于 kmem_cache_alloc 实现128KB最常见的分配方式,需要小于页框大小的内存时可以使用vmalloc建立非连续物理内存到虚拟地址的映射物理不连续,适合需要大内存,但是对地址连续性没有要求的场合dma_alloc_coherent基于_alloc_pages 实现4MB适用于 DMA 操作ioremap实现已知物理地址到虚拟地址的映射适用于物理地址已知的场合,如设备驱动alloc_bootmem在启动 kernel 时,预留一段内存,内核看不见小于物理内存大小,内存管理要求较高

    4、malloc 申请内存

    ·调用 malloc 函数时,它沿 free_chuck_list 连接表寻找一个大到足以满足用户请求所需要的内存块

    6307edc6727f645eb5d93d217b4446f7.png

    ·free_chuck_list 连接表的主要工作是维护一个空闲的堆空间缓冲区链表

    ·如果空间缓冲区链表没有找到对应的节点,需要通过系统调用 sys_brk 延伸进程的栈空间

    5fd0fe599f9c72d1b2903847216e2730.png

    5、缺页异常

    ·通过 get_free_pages 申请一个或多个物理页面

    ·换算 addr 在进程 pdg 映射中所在的 pte 地址

    ·将 addr 对应的 pte 设置为物理页面的首地址

    ·系统调用:Brk—申请内存小于等于 128kb,do_map—申请内存大于 128kb

    3771b911f564f3503a43f802783cb73a.png

    6、用户进程访问内存分析

    ·用户态进程独占虚拟地址空间,两个进程的虚拟地址可相同

    ·在访问用户态虚拟地址空间时,如果没有映射物理地址,通过系统调用发出缺页异常

    ·缺页异常陷入内核,分配物理地址空间,与用户态虚拟地址建立映射

    63eb37621b7c1194574fd66dae8fcc34.png

    7、共享内存

    1) 原理

    ·它允许多个不相关的进程去访问同一部分逻辑内存

    ·两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案

    ·两个运行中的进程共享数据,是进程间通信的高效方法,可有效减少数据拷贝的次数

    32430cc7e04afe5af5fc7aa33cabc75c.png

    2) shm 接口

    ·shmget 创建共享内存

    ·shmat 启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间

    ·shmdt 将共享内存从当前进程中分离

    内存使用那些坑

    1、C 内存泄露

    ·在类的构造函数和析构函数中没有匹配地调用 new 和 delete 函数

    133ede8ae8e33d9d5973dd4328ae8cfc.png

    ·没有正确地清除嵌套的对象指针

    ·没有将基类的析构函数定义为虚函数

    ·当基类的指针指向子类对象时,如果基类的析构函数不是 virtual,那么子类的析构函数将不会被调用,子类的资源没有得到正确释放,因此造成内存泄露

    ·缺少拷贝构造函数,按值传递会调用(拷贝)构造函数,引用传递不会调用

    ·指向对象的指针数组不等同于对象数组,数组中存放的是指向对象的指针,不仅要释放每个对象的空间,还要释放每个指针的空间

    ·缺少重载赋值运算符,也是逐个成员拷贝的方式复制对象,如果这个类的大小是可变的,那么结果就是造成内存泄露

    2、C野指针

    ·指针变量没有初始化

    ·指针被 free 或 delete 后,没有设置为 NULL

    ·指针操作超越了变量的作用范围,比如返回指向栈内存的指针就是野指针

    ·访问空指针(需要做空判断)

    ·sizeof 无法获取数组的大小

    ·试图修改常量,如:char p="1234";p='1';

    3、C 资源访问冲突

    ·多线程共享变量没有用 valotile 修饰

    ·多线程访问全局变量未加锁

    ·全局变量仅对单进程有效

    ·多进程写共享内存数据,未做同步处理

    ·mmap 内存映射,多进程不安全

    4、STL迭代器失效

    ·被删除的迭代器失效

    ·添加元素(insert/push_back 等)、删除元素导致顺序容器迭代器失效

    ·错误示例:删除当前迭代器,迭代器会失效

    2d52e562aea8ad42ac53424a08404593.png

    正确示例:迭代器 erase 时,需保存下一个迭代器

    1c0b276fd022d377505290275cb8c89d.png

    5、C++ 11 智能指针

    ·auto_ptr 替换为 unique_ptr

    b4ed695f66b940f8c6378e73cbadc130.png

    ·使用 make_shared 初始化一个 shared_ptr

    f312e6951cd36a15f8354d58b7fd0cb5.png

    ·weak_ptr 智能指针助手

    1)原理分析:

    47a4e9c1f8311f24ed083850d5622725.png

    2)数据结构:

    ccc8af3b032f3d5bba33dca81c92056d.png

    3)使用方法:a. lock() 获取所管理的对象的强引用指针 b. expired() 检测所管理的对象是否已经释放 c. get() 访问智能指针对象

    6、C++ 11 更小更快更安全

    ·std::atomic 原子数据类型多线程安全

    ·std::array长数组开销比 array 小和 std::vector 不同的是 array 的长度是固定的,不能动态拓展

    ·std::vector vector 瘦身 shrink_to_fit():将 capacity 减少为于 size() 相同的大小

    ·td::forward_list

    forward_list 是单链表(std::list 是双链表),只需要顺序遍历的场合,forward_list 能更加节省内存,插入和删除的性能高于 list

    ·std::unordered_map、std::unordered_set用 hash 实现的无序的容器,插入、删除和查找的时间复杂度都是 O(1),在不关注容器内元素顺序的场合,使用 unordered 的容器能获得更高的性能六、 如何查看内存

    ·系统中内存使用情况:/proc/meminfo

    577c222bc9c9d00218c7a87a251227d0.png

    ·进程的内存使用情况:/proc/28040/status

    ·查询内存总使用率:free

    2f88c4a0f15b145c2d3df978194b4faa.png

    ·查询进程 cpu 和内存使用占比:top

    34ba640e23c7e993c39ba677a522cade.png

    ·虚拟内存统计:vmstat

    8273a80345fa4d39c32d9f246423e2dc.png

    ·进程消耗内存占比和排序:ps aux –sort -rss

    2ffe18dc0d486420268bf1ef1306c961.png

    ·释放系统内存缓存:/proc/sys/vm/drop_caches

    To free dentries and inodes, use echo 2 > /proc/sys/vm/drop_caches

    To free pagecache, dentries and inodes, use echo 3 >/proc/sys/vm/drop_caches

    免责声明:本文来源网络,版权归原作者所有。如涉及作品版权问题,请与我联系删除。

    展开全文
  • 本文主要介绍Linux内存组织结构和页面布局,内存碎片产生原因和优化算法,Linux内核几种内存管理的方法,内存使用场景以及内存使用的那些坑。从内存的原理和结构,到内存的算法优化,再到使用场景,去探寻内存管理的...

    Linux内存是后台开发人员,需要深入了解的计算机资源。合理的使用内存,有助于提升机器的性能和稳定性。本文主要介绍Linux内存组织结构和页面布局,内存碎片产生原因和优化算法,Linux内核几种内存管理的方法,内存使用场景以及内存使用的那些坑。

    从内存的原理和结构,到内存的算法优化,再到使用场景,去探寻内存管理的机制和奥秘。

    一、走进Linux内存

    1、内存是什么?1)内存又称主存,是CPU能直接寻址的存储空间,由半导体器件制成2)内存的特点是存取速率快

    2、内存的作用

    1)暂时存放cpu的运算数据

    2)硬盘等外部存储器交换的数据

    3)保障cpu计算的稳定性和高性能

    二、Linux内存地址空间

    1、Linux内存地址空间Linux内存管理全貌

    2、内存地址——用户态&内核态

    用户态:Ring3运行于用户态的代码则要受到处理器的诸多

    内核态:Ring0在处理器的存储保护中,核心态

    用户态切换到内核态的3种方式:系统调用、异常、外设中断

    区别:每个进程都有完全属于自己的,独立的,不被干扰的内存空间;用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用;内核态线程共享内核地址空间;

    3、内存地址——MMU地址转换

    MMU是一种硬件电路,它包含两个部件,一个是分段部件,一个是分页部件

    分段机制把一个逻辑地址转换为线性地址

    分页机制把一个线性地址转换为物理地址

    4、内存地址——分段机制1)段选择符

    为了方便快速检索段选择符,处理器提供了6个分段寄存器来缓存段选择符,它们是:cs,ss,ds,es,fs和gs

    段的基地址(BaseAddress):在线性地址空间中段的起始地址

    段的界限(Limit):在虚拟地址空间中,段内可以使用的最大偏移量

    2)分段实现

    逻辑地址的段寄存器中的值提供段描述符,然后从段描述符中得到段基址和段界限,然后加上逻辑地址的偏移量,就得到了线性地址

    5、内存地址——分页机制(32位)

    分页机制是在分段机制之后进行的,它进一步将线性地址转换为物理地址

    10位页目录,10位页表项,12位页偏移地址

    单页的大小为4KB

    6、用户态地址空间

    TEXT:代码段可执行代码、字符串字面值、只读变量

    DATA:数据段,映射程序中已经初始化的全局变量

    BSS段:存放程序中未初始化的全局变量

    HEAP:运行时的堆,在程序运行中使用malloc申请的内存区域

    MMAP:共享库及匿名文件的映射区域

    STACK:用户进程栈

    7、内核态地址空间

    直接映射区:线性空间中从3G开始最大896M的区间,为直接内存映射区

    动态内存映射区:该区域由内核函数vmalloc来分配

    永久内存映射区:该区域可访问高端内存

    固定映射区:该区域和4G的顶端只有4k的隔离带,其每个地址项都服务于特定的用途,如:ACPI_BASE等

    8、进程内存空间

    用户进程通常情况只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址

    内核空间是由内核负责映射,不会跟着进程变化;内核空间地址有自己对应的页表,用户进程各自有不同额页表

    三、Linux内存分配算法

    内存管理算法:对讨厌自己管理内存的人来说是天赐的礼物。1、内存碎片1)基本原理

    产生原因:内存分配较小,并且分配的这些小的内存生存周期又较长,反复申请后将产生内存碎片的出现

    优点:提高分配速度,便于内存管理,防止内存泄露

    缺点:大量的内存碎片会使系统缓慢,内存使用率低,浪费大

    2)如何避免内存碎片

    少用动态内存分配的函数(尽量使用栈空间)

    分配内存和释放的内存尽量在同一个函数中

    尽量一次性申请较大的内存,而不要反复申请小内存

    尽可能申请大块的2的指数幂大小的内存空间

    外部碎片避免——伙伴系统算法

    内部碎片避免——slab算法

    自己进行内存管理工作,设计内存池

    2、伙伴系统算法——组织结构1)概念

    为内核提供了一种用于分配一组连续的页而建立的一种高效的分配策略,并有效的解决了外碎片问题

    分配的内存区是以页框为基本单位的

    2)外部碎片

    外部碎片指的是还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域3)组织结构

    把所有的空闲页分组为11个块链表,每个块链表分别包含大小为1,2,4,8,16,32,64,128,256,512和1024个连续页框的页块。最大可以申请1024个连续页,对应4MB大小的连续内存。

    3、伙伴系统算法——申请和回收1)申请算法

    申请2^i个页块存储空间,如果2^i对应的块链表有空闲页块,则分配给应用

    如果没有空闲页块,则查找2^(i1)对应的块链表是否有空闲页块,如果有,则分配2^i块链表节点给应用,另外2^i块链表节点插入到2^i对应的块链表中

    如果2^(i1)块链表中没有空闲页块,则重复步骤2,直到找到有空闲页块的块链表

    如果仍然没有,则返回内存分配失败

    2)回收算法

    释放2^i个页块存储空间,查找2^i个页块对应的块链表,是否有与其物理地址是连续的页块,如果没有,则无需合并

    如果有,则合并成2^(i1)的页块,以此类推,继续查找下一级块链接,直到不能合并为止

    3)条件

    两个块具有相同的大小

    它们的物理地址是连续的

    页块大小相同

    4、如何分配4M以上内存?1)为何限制大块内存分配

    分配的内存越大,失败的可能性越大

    大块内存使用场景少

    2)内核中获取4M以上大内存的方法

    修改MAX_ORDER,重新编译内核

    内核启动选型传递'mem='参数,如'mem=80M,预留部分内存;然后通过

    request_mem_region和ioremap_nocache将预留的内存映射到模块中。需要修改内核启动参数,无需重新编译内核.但这种方法不支持x86架构,只支持ARM,PowerPC等非x86架构

    在start_kernel中mem_init函数之前调用alloc_boot_mem函数预分配大块内存,需要重新编译内核

    vmalloc函数,内核代码使用它来分配在虚拟内存中连续但在物理内存中不一定连续的内存

    5、伙伴系统——反碎片机制1)不可移动页

    这些页在内存中有固定的位置,不能够移动,也不可回收

    内核代码段,数据段,内核kmalloc()出来的内存,内核线程占用的内存等

    2)可回收页

    这些页不能移动,但可以删除。内核在回收页占据了太多的内存时或者内存短缺时进行页面回收3)可移动页

    这些页可以任意移动,用户空间应用程序使用的页都属于该类别。它们是通过页表映射的

    当它们移动到新的位置,页表项也会相应的更新

    6、slab算法——基本原理1)基本概念

    Linux所使用的slab分配器的基础是JeffBonwick为SunOS操作系统首次引入的一种算法

    它的基本思想是将内核中经常使用的对象放到高速缓存中,并且由系统保持为初始的可利用状态。比如进程描述符,内核中会频繁对此数据进行申请和释放

    2)内部碎片

    已经被分配出去的的内存空间大于请求所需的内存空间3)基本目标

    减少伙伴算法在分配小块连续内存时所产生的内部碎片

    将频繁使用的对象缓存起来,减少分配、初始化和释放对象的时间开销

    通过着色技术调整对象以更好的使用硬件高速缓存

    7、slab分配器的结构

    由于对象是从slab中分配和释放的,因此单个slab可以在slab列表之间进行移动

    slabs_empty列表中的slab是进行回收(reaping)的主要备选对象

    slab还支持通用对象的初始化,从而避免了为同一目而对一个对象重复进行初始化

    8、slab高速缓存1)普通高速缓存

    slab分配器所提供的小块连续内存的分配是通过通用高速缓存实现的

    通用高速缓存所提供的对象具有几何分布的大小,范围为32到131072字节。

    内核中提供了kmalloc()和kfree()两个接口分别进行内存的申请和释放

    2)专用高速缓存

    内核为专用高速缓存的申请和释放提供了一套完整的接口,根据所传入的参数为具体的对象分配slab缓存

    kmem_cache_create()用于对一个指定的对象创建高速缓存。它从cache_cache普通高速缓存中为新的专有缓存分配一个高速缓存描述符,并把这个描述符插入到高速缓存描述符形成的cache_chain链表中

    kmem_cache_alloc()在其参数所指定的高速缓存中分配一个slab。相反,kmem_cache_free()在其参数所指定的高速缓存中释放一个slab

    9、内核态内存池1)基本原理

    先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用

    当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存

    这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升

    2)内核API

    mempool_create创建内存池对象

    mempool_alloc分配函数获得该对象

    mempool_free释放一个对象

    mempool_destroy销毁内存池

    10、用户态内存池1)C++++实例

    11、DMA内存1)什么是DMA

    能向CPU发出系统保持(HOLD)信号,提出总线接管请求

    当CPU发出允许接管信号后,负责对总线的控制,进入DMA方式

    能对存储器寻址及能修改地址指针,实现对内存的读写操作

    能决定本次DMA传送的字节数,判断DMA传送是否结束

    发出DMA结束信号,使CPU恢复正常工作状态

    2)DMA信号

    DREQ:DMA请求信号。是外设向DMA控制器提出要求,DMA操作的申请信号

    DACK:DMA响应信号。是DMA控制器向提出DMA请求的外设表示已收到请求和正进行处理的信号

    HRQ:DMA控制器向CPU发出的信号,要求接管总线的请求信号。

    HLDA:CPU向DMA控制器发出的信号,允许接管总线的应答信号:

    四、内存使用场景

    outofmemory的时代过去了吗?no,内存再充足也不可任性使用。1、内存的使用场景

    page管理

    slab(kmalloc、内存池)

    用户态内存使用(malloc、relloc文件映射、共享内存)

    程序的内存map(栈、堆、code、data)

    内核和用户态的数据传递(copy_from_user、copy_to_user)

    内存映射(硬件寄存器、保留内存)

    DMA内存

    2、用户态内存分配函数

    alloca是向栈申请内存,因此无需释放

    malloc所分配的内存空间未被初始化,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内存空间已被重新分配)可能会出现问题

    calloc会将所分配的内存空间中的每一位都初始化为零

    realloc扩展现有内存空间大小

    a)如果当前连续内存块足够realloc的话,只是将p所指向的空间扩大,并返回p的指针地址。这个时候q和p指向的地址是一样的

    b)如果当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将p指向的内容copy到q,返回q。并将p所指向的内存空间删除

    3、内核态内存分配函数函数分配原理最大内存其他_get_free_pages直接对页框进行操作4MB适用于分配较大量的连续物理内存kmem_cache_alloc基于slab机制实现128KB适合需要频繁申请释放相同大小内存块时使用kmalloc基于kmem_cache_alloc实现128KB最常见的分配方式,需要小于页框大小的内存时可以使用vmalloc建立非连续物理内存到虚拟地址的映射物理不连续,适合需要大内存,但是对地址连续性没有要求的场合dma_alloc_coherent基于_alloc_pages实现4MB适用于DMA操作ioremap实现已知物理地址到虚拟地址的映射适用于物理地址已知的场合,如设备驱动alloc_bootmem在启动kernel时,预留一段内存,内核看不见小于物理内存大小,内存管理要求较高4、malloc申请内存

    调用malloc函数时,它沿free_chuck_list连接表寻找一个大到足以满足用户请求所需要的内存块

    free_chuck_list连接表的主要工作是维护一个空闲的堆空间缓冲区链表

    如果空间缓冲区链表没有找到对应的节点,需要通过系统调用sys_brk延伸进程的栈空间

    5、缺页异常

    通过get_free_pages申请一个或多个物理页面

    换算addr在进程pdg映射中所在的pte地址

    将addr对应的pte设置为物理页面的首地址

    系统调用:Brk—申请内存小于等于128kb,do_map—申请内存大于128kb

    6、用户进程访问内存分析

    用户态进程独占虚拟地址空间,两个进程的虚拟地址可相同

    在访问用户态虚拟地址空间时,如果没有映射物理地址,通过系统调用发出缺页异常

    缺页异常陷入内核,分配物理地址空间,与用户态虚拟地址建立映射

    7、共享内存1)原理

    它允许多个不相关的进程去访问同一部分逻辑内存

    两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案

    两个运行中的进程共享数据,是进程间通信的高效方法,可有效减少数据拷贝的次数

    2)Shm接口

    shmget创建共享内存

    shmat启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间

    shmdt将共享内存从当前进程中分离

    五、内存使用那些坑

    1、C内存泄露

    在类的构造函数和析构函数中没有匹配地调用new和delete函数

    没有正确地清除嵌套的对象指针

    没有将基类的析构函数定义为虚函数

    当基类的指针指向子类对象时,如果基类的析构函数不是virtual,那么子类的析构函数将不会被调用,子类的资源没有得到正确释放,因此造成内存泄露

    缺少拷贝构造函数,按值传递会调用(拷贝)构造函数,引用传递不会调用

    指向对象的指针数组不等同于对象数组,数组中存放的是指向对象的指针,不仅要释放每个对象的空间,还要释放每个指针的空间

    缺少重载赋值运算符,也是逐个成员拷贝的方式复制对象,如果这个类的大小是可变的,那么结果就是造成内存泄露

    2、C野指针

    指针变量没有初始化

    指针被free或delete后,没有设置为NULL

    指针操作超越了变量的作用范围,比如返回指向栈内存的指针就是野指针

    访问空指针(需要做空判断)

    sizeof无法获取数组的大小

    试图修改常量,如:charp='1234';p='1';

    3、C资源访问冲突

    多线程共享变量没有用valotile修饰

    多线程访问全局变量未加锁

    全局变量仅对单进程有效

    多进程写共享内存数据,未做同步处理

    mmap内存映射,多进程不安全

    4、STL迭代器失效

    被删除的迭代器失效

    添加元素(insert/push_back等)、删除元素导致顺序容器迭代器失效

    错误示例:删除当前迭代器,迭代器会失效

    正确示例:迭代器erase时,需保存下一个迭代器

    5、C++11智能指针

    auto_ptr替换为unique_ptr

    使用make_shared初始化一个shared_ptr

    weak_ptr智能指针助手(1)原理分析:

    (2)数据结构:

    (3)使用方法:a.lock()获取所管理的对象的强引用指针b.expired()检测所管理的对象是否已经释放c.get()访问智能指针对象

    6、C++11更小更快更安全

    std::atomic原子数据类型多线程安全

    std::array定长数组开销比array小和std::vector不同的是array的长度是固定的,不能动态拓展

    std::vectorvector瘦身shrink_to_fit():将capacity减少为于size()相同的大小

    td::forward_list

    forward_list是单链表(std::list是双链表),只需要顺序遍历的场合,forward_list能更加节省内存,插入和删除的性能高于list

    std::unordered_map、std::unordered_set用hash实现的无序的容器,插入、删除和查找的时间复杂度都是O(1),在不关注容器内元素顺序的场合,使用unordered的容器能获得更高的性能六、如何查看内存

    系统中内存使用情况:/proc/meminfo

    进程的内存使用情况:/proc/28040/status

    查询内存总使用率:free

    查询进程cpu和内存使用占比:top

    虚拟内存统计:vmstat

    进程消耗内存占比和排序:psaux–sort-rss

    释放系统内存缓存:/proc/sys/vm/drop_caches

    Tofreepagecache,useecho1>/proc/sys/vm/drop_caches

    Tofreedentriesandinodes,useecho2>/proc/sys/vm/drop_caches

    Tofreepagecache,dentriesandinodes,useecho3>/proc/sys/vm/drop_caches

    展开全文
  • 操作系统存储和寻址是较为重要一部分,这里面有很多精髓思想在里面,涉及到很多知识点,例如寻址空间(逻辑内存)、物理内存(实际拥有的内存)、虚拟内存(通常在硬盘上,固态或者机械硬盘上开辟空间),...

    操作系统的存储和寻址是较为重要的一部分,这里面有很多精髓的思想在里面,涉及到很多知识点,例如寻址空间(逻辑内存)、物理内存(实际拥有的内存)、虚拟内存(通常在硬盘上,固态或者机械硬盘上开辟的空间),因此我打算通过一种较为形象具体的方法来给大家讲解我的理解。
    先说一下操作系统的存储

    在这里插入图片描述
    计算机的存储主要是层级结构化的,如图所示,从下至上的速度由慢到快,相应的成本也越来越高,所以容量也越来越小,价格越来越贵。
    硬盘:数据长久存放,容量比较大
    内存:关机数据就会消失,快速随机访问
    CPU:运算模块和缓存模块,缓存分为不同级别
    寄存器:离CPU运算单元最近的部分
    好的 那么给出一个地址,如何在层次性的存储结构中找到相关的数据呢,下面就要引入寻址的概念
    首先要讲讲寻址空间,寻址空间为每一个进程可以取到的地址的范围,与机器上物理内存的大小是没有关系的,相当于一个逻辑上的概念,例如32位操作系统的寻址空间为2322^{32}bit,也就是4G,64位的操作系统的寻址空间为2642^{64}bit也就是大概60TB的大小。
    下面举出一个寻址例子
    比如给你一个指针P,如何找出它对应的数据并读出呢?
    int n=*P
    汇编语言为MOV EXA,[EBA]

    在这里插入图片描述
    给出一个指针P,首先其指向的内存为逻辑内存(上面讲的寻址空间),然后计算机操作系统通过建立一个逻辑内存与物理内存的对应关系,但是存在一个问题,因为逻辑内存普遍较大,因此有可能出现逻辑内存大于物理内存的现象,那么多出来的内存在哪里呢?答案就是虚拟内存里面,操作系统一般都会在硬盘空间开辟一块地方用作虚拟内存,假如指针P的寻址指向的是虚拟内存,那么就需要把虚拟内存中的数放入物理内存中,比如指针P指向一个4字节的整数,那么不能每次都这么繁琐的操作吧,所以操作系统中不是仅仅把P这样一个数的数据放过去,而是把P所在的数据分页整体放入物理内存中。
    但是上面所述又存在一个问题,比如一个进程A占用1-200,进程B占用201-205,进程C占用206-300的地址空间,然后进程B结束后,201-205的空间就空出来了,假如这样的情况越来越多,那么内存中就会出现很多细小空闲的空间碎片,这时候操作系统就通过算法找寻出这些细小的空间碎片,然后将这些小碎片空间(不常用的物理内存)汇总交换回硬盘上的虚拟内存里,这样就保证了物理内存的高效性。
    然后接着上面的,当数据被放入物理内存中的时候,接下来的操作就是把数据放入寄存器EXA里面就可以了。
    上面所讲的就是寻址的过程,一个系统如果绝大部分的数据都在物理内存里面,那么系统速度很快,如果物理内存的使用量过多,就会发生频繁的分裂和与硬盘虚拟内存的交换,由于硬盘的速度较慢,所以就会影响到整个系统运行速度的稳定。

    展开全文
  • 虚拟地址关系到进程用户空间内核空间,而物理地址则用来寻址实际可用的内存。 linux用页表来为物理地址分配虚拟地址。 进程虚拟地址空间,都被内核划分为很多等长部分,这样部分成为页。物理内存也划分...
  • DOS用一种分段结构来寻址计算机的内存,每一个物理存储位置...DOS下的每个程序都是按这种方式访问内存的——尽管段一偏移量寻址方法的机理对大多数C程序员来说是隐蔽的。 当你的程序被执行时,一个存放在数据段(...
  • 第7章更灵活定位内存地址的方法 7.1 andor指令 7.2 关于ASCII码 7.3 以字符形式给出数据 7.4 大小写转换问题 7.5 [bx+idata] 7.6 用[bx+idata]方式进行数组处理 7.7 SIDI 7.8 [bx+si][bx+di...
  • 操作系统_A20 Gate

    2021-03-09 21:12:41
    A20 Gate由来键盘控制器8042参考文章 ...PC机的寻址结构是segment:offset,segmentoffset都是16位寄存器,最大值是0ffffh,换算成物理地址计算方法是把segment左移4位,再加上offset,所以segment:of
  • 第7章 更灵活定位内存地址的方法 7.1 andor指令. 7.2 关于ASCII码 7.3 以字符形式给出数据 7.4 大小写转换问题 7.5 [bx+idata]. 7.6 用[bx+idata]方式进行数组处理 7.7 SIDI. 7.8 Lbx+si]...
  • 很强ccna教程

    2013-12-02 15:02:54
    Ethernet/802.3的物理层 物理层设备 集线器运行在物理层 冲突域 广播域 集线器:同一个冲突域 CSMA/CD技术 CSMA/CD工作原理 CSMA/CD重要特性 数据链路层功能 MAC子层 LLC子层 SAP服务访问点 数据链路层功能(续) ...
  • 第7章 更灵活定位内存地址的方法 7.1 andor指令 7.2 关于ASCII码 7.3 以字符形式给出数据 7.4 大小写转换问题 7.5 [bx+idata] 7.6 用[bx+idata]方式进行数组处理 7.7 SIDI 7.8 [bx+si][bx+di] ...
  • 疯狂程序员

    热门讨论 2012-07-18 18:05:32
    室里一个人――不一样,这间寝室有个不属于这个班人――他叫王江。 王江他特别,不仅因为他不是这班,还因为他吹牛皮很特别。 大一晚上谈什么?当然是谈高考。 于是王江就叹息:哎呀,差一分呐。 土匪...
  • 又介绍了采用32位CPU微型计算机系统的内存结构和典型的内存设计模式,这部分内容较难理解,不要求掌握,只要对此有所了解就可以了。半导体存储器性能指标是选择存储器主要依据,所以介绍了几个选择存储器...
  • 2.68086CPU给出物理地址的方法 2.7“段地址×16+偏移地址=物理地址” 本质含义 2.8段概念 2.9段寄存器 2.10CSIP 2.11修改CS、IP指令 2.12代码段 实验1查看CPU和内存,用机器指令 汇编指令编程 第3章寄存器...
  • 汇编课程研究重点放在如何利用硬件系统编程结构和指令集有效灵活控制系统进行工作。 1.1 机器语言 机器语言是机器指令集合。 机器指令展开来讲就是一台机器可以正确执行命令。 1.1 机器语言 指令:...
  • 这并不是我们所希望看到事情,因为任何不以循序渐进方式进行学习,都将出现盲目探索不成系统情况,最终学习到也大都是相对零散知识,并不能建立起一个系统知识结构.非循序渐进学习,也达不到循序渐进...
  • (2)一个存放在8086计算机系统内存中的数据,它以DS作为段基址寄存器且设(DS)=1000H,段内偏移地址为2300H,会计算该数据的物理地址(同样是:段基地址左移4位+段内偏移地址),指向这一物理地址的DS值段内偏移...
  • 微机学习要求答案

    2018-11-27 19:19:38
    (2)一个存放在8086计算机系统内存中的数据,它以DS作为段基址寄存器且设(DS)=1000H,段内偏移地址为2300H,会计算该数据的物理地址(同样是:段基地址左移4位+段内偏移地址),指向这一物理地址的DS值段内偏移...
  • 7.给定一个存放数据的内存单元的偏移地址是20C0H,(DS)=0C00EH,求出该内存单元的物理地址。 答:物理地址:320F8H。 8.8086/8088为什么采用地址/数据引线复用技术? 答:考虑到芯片成本,8086/8088采用40条引线...
  • 4.4 物理内存的分配与回收 83 4.4.1 伙伴算法 85 4.4.2 物理页面的分配 86 4.4.3 物理页面的回收 88 4.4.4 slab分配模式 89 4.4.5 内核空间非连续内存区的分配 93 4.5 交换机制 95 4.5.1 交换的基本原理 95 4.5.2 ...
  • 编程卓越之道:卷一/二

    热门讨论 2010-10-10 08:31:04
    9.4.4 指令高速缓存——提供访问内存的多条通路 247 9.4.5 流水线相关(pipeline hazards) 249 9.4.6 超标量运算——并行执行指令 251 9.4.7 乱序执行(Out-of-Order Execution) 253 9.4.8 寄存器重命名 253 ...
  • d-SEAMS:具有NixC++Lua实现分子动力学轨道分析引擎,它是分子模拟递延结构分析首字母缩写。 gromacs:传递消息并行分子动力学实现。 Reaktoro:C++python中用于对化学反应系统进行建模计算框架。...
  • 4.3.1内存资源管理 4.3.2接受连接的方法 4.3.3恶意客户连接问题 4.3.4包重新排序问题 4.4可伸缩服务器系统设计实例 4.4.1 CIOCPServer类总体结构 4.4.2数据结构定义和内存池方案 4.4.3自定义帮助函数 4.4.4开启...

空空如也

空空如也

1 2 3
收藏数 57
精华内容 22
关键字:

内存的物理结构和寻址方法