精华内容
下载资源
问答
  • 内存管理

    千次阅读 2018-06-11 21:21:46
    一、实验目的( 1) 通过对 Windows xp“任务管理器”、“计算机管理”、“我的电脑”属性、“系统信息”、“系统监视器”等程序的应用,学习如何察看和调整 Windows 的内存性能,加深对操作系统内存管理、虚拟存储...

    一、实验目的

    1) 通过对 Windows xp“任务管理器”、“计算机管理”、“我的电脑”属性、“系统信息”、“系统监视器”等程序的应用,学习如何察看和调整 Windows 的内存性能,加深对操作系统内存管理、虚拟存储管理等理论知识的理解。
         2) 了解 Windows xp 的内存结构和虚拟内存的管理,理解进程的虚拟内存空间和物理内存的映射关系。

    二、总体设计

        2.1 设计步骤

    1)观察和调整 Windows XP 的内存性能。

    步骤 1:阅读“背景知识”,请回答:

    1) 什么是“分页过程”?

    2) 什么是“内存共享”?

    3) 什么是“未分页合并内存”和“分页合并内存”?

    Windows xp 中,未分页合并内存的最大限制是多少?

    4) Windows xp 分页文件默认设置的最小容量和最大容量是多少?

    步骤 2:登录进入 Windows xp。

    步骤 3:查看包含多个实例的应用程序的内存需求。

    1) 启动想要监视的应用程序,例如 Word。

    2) 右键单击任务栏以启动“任务管理器”。

    3) 在“Windows 任务管理器”对话框中选定“进程”选项卡。

    4) 向下滚动在系统上运行的进程列表,查找想要监视的应用程序。

    请在表 5-3 中记录:

          5-3 实验记录

    映像名称

    PID

    CPU

    CPU 时间

    内存使用

    Winword.exe*32

    796

    01

    0:02:04

    39,164k

       “内存使用”列显示了该应用程序的一个实例正在使用的内存数量。
        5) 启动应用程序的另一个实例并观察它的内存需求。
        请描述使用第二个实例占用的内存与使用第一个实例时的内存对比情况。
        步骤 4:未分页合并内存。
        估算未分页合并内存大小的最简单方法是使用“任务管理器”。未分页合并内存的估计值显示在“任务管理器”的“性能”选项卡的“核心内存”部分。
    总数 (K) : __________289_________ 分页数: ___________198___________
    未分页 (K) : ________91_______________
        还可以使用“任务管理器”查看一个独立进程正在使用的未分页合并内存数量和分页合并内存数量。操作步骤如下:
        1) 单击“Windows 任务管理器”的“进程”选项卡,然后从“查看”菜单中选择“选择列”命令,显示“进程”选项卡的可查看选项

    2)在“选择列”对话框中,选定“页面缓冲池”选项和“非页面缓冲池”选项旁边的复选框,然后单击“确定”按钮。
        返回 Windows Xp“任务管理器”的“进程”选项卡时,将看到其中增加显示了各个进程占用的分页合并内存数量和未分页合并内存数量。
        仍以刚才打开观察的应用程序 (例如 Word) 为例,请在表 5-4 中记录:

    5-4 实验记录

    映像名称

    PID

    内存使用

    页面缓冲池

    非页面缓冲池

    Winword.exe*32

    796

    01

    1,044k

    89k

    从性能的角度来看,未分页合并内存越多,可以加载到这个空间的数据就越多。拥有的物理内存越多,未分页合并内存就越多。但未分页合并内存被限制为 256MB,因此添加超出这个限制的内存对未分页合并内存没有影响。
        步骤 5:提高分页性能。

    Windows xp 的安装过程中,将使用连续的磁盘空间自动创建分页文件(pagefile.sys) 。用户可以事先监视变化的内存需求并正确配置分页文件,使得当系统必须借助于分页时的性能达到最高。
        虽然分页文件一般都放在系统分区的根目录下面,但这并不总是该文件的最佳位置。要想从分页获得最佳性能,应该首先检查系统的磁盘子系统的配置,以了解它是否有多个物理硬盘驱动器。

    1) 在“开始”菜单中单击“设置” – “控制面板”命令,双击“管理工具”图标,再双击“计算机管理”图标。

    2) 在“计算机管理”窗口的左格选择“磁盘管理”管理单元来查看系统的磁盘配置。请在表 5-5 中记录:

    5-5 实验记录

    布局

    类型

    文件系统

    容量

    状态

    C:

    简单

    基本

    NTFS

    100.00GB

    系统,启动,页面文件,活动,故障转储,主分区

    D:

    简单

    基本

    NTFS

    30GB

    逻辑驱动器

    E:

    简单

    基本

    NTFS

    30GB

    逻辑驱动器

    F:

    简单

    基本

    NTFS

    100GB

    逻辑驱动器

     

    简单

    基本

     

    4.88GB

    OEM分区

        如果系统只有一个硬盘,那么建议应该尽可能为系统配置额外的驱动器。这是因为: Windows xp 最多可以支持在多个驱动器上分布的 16 个独立的分页文件。为系统配置多个分页文件可以实现对不同磁盘 I/O 请求的并行处理,这将大大提高 I/O 请求的分页文件性能。
        步骤 6:计算分页文件的大小。
        要想更改分页文件的位置或大小配置参数,可按以下步骤进行:
        1) 右键单击桌面上的“我的电脑”(Win7 为计算机)图标并选定“属性”(Win7 为高级系统设置)。
        2) 在“高级”选项卡上单击“性能选项”按钮。
        3) 单击对话框中的“虚拟内存”区域中的“更改”按钮。
        请记录:
        所选驱动器 (C: ) 的页面文件大小:
    驱动器: ___________C:__________ 可用空间: _______70103_______ MB
        初始大小 (MB) : ________16________ 最大值 (MB) : ______5648____
    所选驱动器 (D: ) 的页面文件大小: (如果有的话)
        驱动器: _________D:__________ 可用空间: _____30621________MB
        初始大小 (MB) : ______16_________ 最大值 (MB) : ______6531_____
    所有驱动器页面文件大小的总数:
    允许的最小值: ______16_____ MB 推荐: ______12183_____ MB
    当前已分配: ________8122____ MB
        4) 要想将另一个分页文件添加到现有配置,在“虚拟内存”对话框中选定一个还没有分页文件的驱动器,然后指定分页文件的初始值和最大值 (以兆字节表示) ,单击“设置”,然后单击“确定”。
        5) 要想更改现有分页文件的最大值和最小值,可选定分页文件所在的驱动器。然后指定分页文件的初始值和最大值,单击“设置”按钮,然后单击“确定”按钮。
        6) 在“性能选项”对话框中单击“确定”按钮。
        7) 单击“确定”按钮以关闭“系统特性”对话框。
        2)了解和检测进程的虚拟内存空间。
        步骤 1: 创建一个“Win32 Consol Application”工程,然后拷贝清单 5-1 中的程序,编译成可执行文件。
        步骤 2:  VC 的工具栏单击“Execute Program” (执行程序) 按钮,或者按 Ctrl + F5 键,或者在“命令提示符”窗口运行步骤 1 中生成的可执行文件。
        步骤 3: 根据运行结果,回答下列问题
    虚拟内存每页容量为: ____4.00KB______ 最小应用地址:____0x00010000_____
    最大应用地址: ______________0x7ffeffff____________________________
    当前可供应用程序使用的内存空间为: 1.99GB
    当前计算机的实际内存大小为:8GB
    理论上每个 Windows 应用程序可以独占的最大存储空间是:264字节(64位系统);4GB(32位系统)

    committed、 reserved、 free 等三种虚拟地址空间分别记录实验数据。其中“描述”是指对该组数据的简单描述,例如,对下列一组数据:
        00010000 – 00012000 <8.00KB> Committed, READWRITE, Private可描述为:具有 READWRITE 权限的已调配私有内存区。
        记录系统当前虚拟地址空间(部分)

    00010000-00020000

    64.0 KB

    Committed

    READWRITE

    Mapped

    00020000-00030000

    64.0 KB

    Committed

    READWRITE

    Mapped

    00030000-00031000

    4.00 KB

    Committed

    READWRITE

    Private

    00031000-00040000

    60.0 KB

    Free

    NOACCESS

     

    00040000-00041000

    4.00 KB

    Committed

    READONLY

    Image

    00041000-00050000

    60.0 KB

    Free

    NOACCESS

     

    00050000-00089000

    228 KB

    Reserved

    READONLY

    Private

    00089000-0008c000

    12.0 KB

    Committed

    GUARD

    READWRITE,

    Private

    0008c000-00090000

    16.0 KB

    Committed

    READWRITE

    Private

    00090000-0028c000

    1.98 MB

    Reserved

    READONLY

    Private

    0028d000-00290000

    12.0 KB

    Committed

    READWRITE

    Private

    00290000-00294000

    16.0 KB

    Committed

    READONLY

    Mapped

    00294000-002a0000

    48.0 KB

    Free

    NOACCESS

     

    002a0000-002a1000

    4.00 KB

    Committed

    READWRITE

    Private

    002a1000-002b0000

    60.0 KB

    Free

    NOACCESS

     

    002b0000-00317000

    412 KB

    Committed

    READONLY

    Mapped

    00317000-00320000

    36.0 KB

    Free

    NOACCESS

     

    00320000-00321000

    4.00 KB

    Committed

    READWRITE

    Private

    00321000-00330000

    60.0 KB

    Free

    NOACCESS

     

    00330000-00331000

    4.00 KB

    Committed

    READWRITE

    Private

    00331000-00350000

    124 KB

    Reserved

    READONLY

    Private

    00350000-00356000

    24.0 KB

    Committed

    READONLY

    Mapped

    00356000-00360000

    40.0 KB

    Free

    NOACCESS

     

    00360000-00366000

    24.0 KB

    Committed

    READWRITE

    Private

    00366000-003e0000

    488 KB

    Reserved

    READONLY

    Private

    003e0000-003e1000

    4.00 KB

    Committed

    READWRITE

    Mapped

    003e1000-00400000

    124 KB

    Free

    NOACCESS

     

    00400000-00401000

    4.00 KB

    Committed

    READONLY

    Image,Module:666666.exe

    00401000-0047f000

    504 KB

    Committed

    EXECUTE_READ

    Image

    0047f000-00480000

    4.00 KB

    Committed

    READWRITE

    Image

    00480000-0048a000

    40.0 KB

    Committed

    READONLY

    Image

    0048a000-0048c000

    8.00 KB

    Committed

    READWRITE

    Image

    0048c000-00490000

    16.0 KB

    Committed

    WRITECOPY

    Image

     

    三、详细设计

      // 工程 vmwalker
    #include <windows.h>
    #include <iostream>
    #include <shlwapi.h>
    #include <iomanip>
    #pragma comment(lib, "Shlwapi.lib")
    // 以可读方式对用户显示保护的辅助方法。
    // 保护标记表示允许应用程序对内存进行访问的类型
    // 以及操作系统强制访问的类型
    inline bool TestSet(DWORD dwTarget, DWORD dwMask)
    {
    return ((dwTarget &dwMask) == dwMask) ;
    }
    # define SHOWMASK(dwTarget, type) \
    if (TestSet(dwTarget, PAGE_##type) ) \
    {std :: cout << ", " << #type; }
    void ShowProtection(DWORD dwTarget)
    {
    SHOWMASK(dwTarget, READONLY) ;
    SHOWMASK(dwTarget, GUARD) ;
    SHOWMASK(dwTarget, NOCACHE) ;
    SHOWMASK(dwTarget, READWRITE) ;
    SHOWMASK(dwTarget, WRITECOPY) ;
    SHOWMASK(dwTarget, EXECUTE) ;
    SHOWMASK(dwTarget, EXECUTE_READ) ;
    SHOWMASK(dwTarget, EXECUTE_READWRITE) ;
    SHOWMASK(dwTarget, EXECUTE_WRITECOPY) ;
    SHOWMASK(dwTarget, NOACCESS) ;
    }
    // 遍历整个虚拟内存并对用户显示其属性的工作程序的方法
    void WalkVM(HANDLE hProcess)
    {
    // 首先,获得系统信息
    SYSTEM_INFO si;
    :: ZeroMemory(&si, sizeof(si) ) ;
    :: GetSystemInfo(&si) ;
    // 分配要存放信息的缓冲区
    MEMORY_BASIC_INFORMATION mbi;
    :: ZeroMemory(&mbi, sizeof(mbi) ) ;
    // 循环整个应用程序地址空间
    LPCVOID pBlock = (LPVOID) si.lpMinimumApplicationAddress;
    while (pBlock < si.lpMaximumApplicationAddress)
    {
    // 获得下一个虚拟内存块的信息
    if (:: VirtualQueryEx(
    hProcess, // 相关的进程
    pBlock, // 开始位置
    &mbi, // 缓冲区
    sizeof(mbi))==sizeof(mbi) ) // 大小的确认
    {
    // 计算块的结尾及其大小
    LPCVOID pEnd = (PBYTE) pBlock + mbi.RegionSize;
    TCHAR szSize[MAX_PATH];
    :: StrFormatByteSize(mbi.RegionSize, szSize, MAX_PATH) ;
    // 显示块地址和大小
    std :: cout.fill ('0') ;
    std :: cout
    << std :: hex << std :: setw(8) << (DWORD) pBlock
    << "-"
    << std :: hex << std :: setw(8) << (DWORD) pEnd
    << (:: strlen(szSize)==7? " (" : " (") << szSize
    << ") " ;
    // 显示块的状态
    switch(mbi.State)
    {
    case MEM_COMMIT :
    std :: cout << "Committed" ;
    break;
    case MEM_FREE :
    std :: cout << "Free" ;
    break;
    case MEM_RESERVE :
    std :: cout << "Reserved" ;
    break;
    }
    // 显示保护
    if(mbi.Protect==0 && mbi.State!=MEM_FREE)
    { mbi.Protect=PAGE_READONLY; }
    ShowProtection(mbi.Protect);
    // 显示类型
    switch(mbi.Type){
    case MEM_IMAGE :
    std :: cout << ", Image" ;
    break;
    case MEM_MAPPED:
    std :: cout << ", Mapped";
    break;
    case MEM_PRIVATE :
    std :: cout << ", Private" ;
    break;
    }
    // 检验可执行的影像
    TCHAR szFilename [MAX_PATH] ;
    if (:: GetModuleFileName (
    (HMODULE) pBlock, // 实际虚拟内存的模块句柄
    szFilename, //完全指定的文件名称
    MAX_PATH)>0) //实际使用的缓冲区大小
    {
    // 除去路径并显示
    :: PathStripPath(szFilename) ;
    std :: cout << ", Module: " << szFilename;
    }
    std :: cout << std :: endl;
    // 移动块指针以获得下一下个块
    pBlock = pEnd;
    }
    }
    }
    void ShowVirtualMemory()
    {
    // 首先,让我们获得系统信息
    SYSTEM_INFO si;
    :: ZeroMemory(&si, sizeof(si) ) ;
    :: GetSystemInfo(&si) ;
    // 使用外壳辅助程序对一些尺寸进行格式化
    TCHAR szPageSize[MAX_PATH];
    ::StrFormatByteSize(si.dwPageSize, szPageSize, MAX_PATH) ;
    DWORD dwMemSize = (DWORD)si.lpMaximumApplicationAddress -
    (DWORD) si.lpMinimumApplicationAddress;
    TCHAR szMemSize [MAX_PATH] ;
    :: StrFormatByteSize(dwMemSize, szMemSize, MAX_PATH) ;
    // 将内存信息显示出来
    std :: cout << "Virtual memory page size: " << szPageSize << std :: endl;
    std :: cout.fill ('0') ;
    std :: cout << "Minimum application address: 0x"
    << std :: hex << std :: setw(8)
    << (DWORD) si.lpMinimumApplicationAddress
    << std :: endl;
    std :: cout << "Maximum application address: 0x"
    << std :: hex << std :: setw(8)
    << (DWORD) si.lpMaximumApplicationAddress
    << std :: endl;
    std :: cout << "Total available virtual memory: "
    << szMemSize << std :: endl ;
    }
    void main()
    {
    //显示虚拟内存的基本信息
    ShowVirtualMemory();
    // 遍历当前进程的虚拟内存
    ::WalkVM(::GetCurrentProcess());
    }

    四、实验结果与分析

    1)观察和调整 Windows XP 的内存性能。

    步骤1:

      1):“分页过程”是: Windows 求助于硬盘以获得虚拟内存时,这个过程被称为分页 (paging) 。分页就是将信息从主内存移动到磁盘进行临时存储的过程。

    2):“内存共享”是:应用程序经常需要彼此通信和共享信息。

    3):“未分页合并内存”是:分页合并内存是存储迟早需要的可分页代码或数据的内存部分。

    “分页合并内存”是:未分页合并内存包含必须驻留在内存中的占用代码或数据。   

    Windows xp 中,未分页合并内存的最大限制是256M

    4):Windows xp 分页文件默认设置的最小容量是:内存数量的1.5最大容量是:最小容量的两倍。

    步骤3:

    5)第二个实例和第一个实例相比,第二个实例所需内存极少。
    五、小结与心得体会

    通过本实验我 Windows xp“任务管理器”、“计算机管理”、“我的电脑”属性、“系统信息”、“系统监视器”等程序的应用学习学会了如何察看和调整 Windows 的内存性能,加深对操作系统内存管理、虚拟存储管理等理论知识的理解。我还了解 Windows xp 的内存结构和虚拟内存的管理,理解进程的虚拟内存空间和物理内存的映射关系。


    展开全文
  • 其最主要作用和目的? 我百度了一下.是这么回答的-->内存管理是 : 指软件运行时对计算机内存资源的分配和使用的技术。 作用是 : 为了高效的,快速的分配,并且在适当的时候释放和回收内存资源。OC内存管理机制说到...

    什么是内存管理?其最主要作用和目的?

    我百度了一下.是这么回答的-->

    内存管理是 : 指软件运行时对计算机内存资源的分配和使用的技术。 作用是 : 为了高效的,快速的分配,并且在适当的时候释放和回收内存资源。

    OC内存管理机制

    说到OC的内存管理机制 不得不说引用计数

    什么是引用计数?以下是我查看的比较合理的答案-->
    引用计数是 : 最普遍的垃圾回收策略之一。每一个对象都会有一个额外的计数值来表示当前被引用的次数。有新的引用,这个值就会+1;结束引用,这个值会自动-1,直到计数值为0时,对象所指的内存块就会废弃掉被系统回收,从而达到释放内存的目的。

    OC的内存管理机制 我个人感觉有四个词可以解释,"生成","持有","释放","废除".

    在"iOS与OS X多线程和内存管理"这本书上看到的对OC内存管理的方式,一共四条
    1.自己生成的对象,自己所持有.
    2.非自己生成的对象,自己也能持有.
    3.不再需要自己持有的对象时释放掉.
    4.非自己持有的对象无法释放.
    大家经过自己一段时间的开发会发现.其实OC的内存管理方式就是这样.


    当然ARC中的内存管理都交给系统来做了 管理方式这篇文章写的比较好 https://www.jianshu.com/p/48665652e4e4 可以做参考 之后小弟也会自己写一篇关系ARC内存管理这一块的文章出来,把自己的见解说出来.
    该文章纯属自己看书期间有感而发,加上之前面试遇到过这几个问题,并没有能系统的说出这几个问题的答案的原因才写出来的,如果有小哥看到该篇文章,并发现哪里有问题,可以随时纠正,小弟在此谢过了!


    转载于:https://juejin.im/post/5a5df99cf265da3e303c7fc0

    展开全文
  • 实现自己的内存管理程序。 题目:统计程序使用内存块大小的频率,实现内存管理程序。目的为减少外部碎片,(宁可换取内部碎片)功能包括 ①初始化内存区域 ②申请内存,返回内存首地址 ③释放内存 ④展示内存占用...

    嵌入式管理,第一个小作业。实现自己的内存管理程序。


    题目:统计程序使用内存块大小的频率,实现内存管理程序。目的为减少外部碎片,(宁可换取内部碎片)功能包括

    ①初始化内存区域

    ②申请内存,返回内存首地址

    ③释放内存

    ④展示内存占用情况


    情景假设:如程序经常使用30-50字节的小块内存区域,较长使用500-1000的大块内存区域,以及较少的1000+的内存区域。


    实现思路:

    1.设计模型

    (1)对于小内存块(SMALLSIZE字节)和大内存块(BIGSIZE字节)的管理如下图。


    该部分共有四个数据结构 ↓

    /*小内存块结构*/
    typedef struct{
    	char data[SMALLSIZE];/*存放data域*/
    }small_block;
    
    /*大内存块结构 */ 
    typedef struct{
    	char data[BIGSIZE];/*存放data域*/
    }big_block;
    
    /*小内存块管理结构*/ 
    typedef struct{
    	small_block * base_add;/*小内存块的基地址*/
    	int busy_num;/*被使用的数量 */
    	char busy[SMALLNUM];/*每个小内存块的使用情况*/ 
    }small_block_manage;
    
    /*大内存块管理结构*/ 
    typedef struct{
    	big_block * base_add;/*大内存块的基地址*/
    	int busy_num;/*被使用的数量 */
    	char busy[BIGNUM]; /*每个大内存块的使用情况*/ 
    }big_block_manage; 

    #define SMALLSIZE 50     /*小内存块数据域的大小 */
    #define SMALLNUM 20      /*小内存块的个数 */
    #define BIGSIZE 1000     /*大内存块数据域的大小 */
    #define BIGNUM 4         /*大内存块的个数 */

    ①小内存块为SMALLSIZE(50)字节,用于用户对小内存的使用。共SMALLNUM(20)个连续的小内存块。

    ②大内存块为BIGSIZE(1000)字节,用户用户对大内存的使用。共BIGNUMM(4)个连续的大内存块。

    ③小内存块管理结构,base_add记录连续的小内存块中 首块 小内存块的地址,busy_num记录小内存块被使用的数量,busy[SMALLNUM]记录小内存块具体使用情况。available可用,busy已占用。

    ④大内存块管理结构,与③类似。

    #define BLOCKAVAILABLE 0
    #define BLOCKBUSY 1


    计算好小内存块和大内存块占用的总字节数,调用原有的malloc函数,申请一大块连续的包含管理区域与内存区域的地址。(申请pre_alloc_size字节。)

    /*计算首先要申请多少字节的内存地址*/ 
    	small_size = SMALLNUM*sizeof(small_block);
    	big_size = BIGNUM*sizeof(big_block);
    	manage_size = sizeof(small_block_manage) + sizeof(big_block_manage);
    	pre_alloc_size = small_size + big_size + manage_size;
    	
    	printf(" ========================================================\n"); 
    	printf("||\t小内存块数量:%d,每块占用%d字节,共%d字节\t||\n",SMALLNUM,sizeof(small_block),small_size); 
    	printf("||\t大内存块数量:%d,每块占用%d字节,共%d字节\t||\n",BIGNUM,sizeof(big_block),big_size); 
    	printf("||\t小内存管理块占用%d字节\t\t\t\t||\n",sizeof(small_block_manage));
    	printf("||\t大内存管理块占用%d字节\t\t\t\t||\n",sizeof(big_block_manage));
    	printf("||\t初始化时总共需申请%d字节的内存区域\t\t||\n",pre_alloc_size);
    	printf(" =========================================================\n");

    可以看下截图



    (2)对于超过1000字节的大内存块,从堆中申请,管理模式如下 ↓( 使用一个带有头结点的链表)

    p_head为头,p_tail为尾


    数据结构定义如下 ↓ 

    typedef struct{
    	int * heap_add;/*记录从heap申请的内存块的地址 */
    	int size;/*该首地址的内存区占用多少字节 */
    	struct heap_add_node *next;/*指向下一个内存区域 */
    }heap_add_node; 

    2.初始化部分  mem_init()

    (1)初始化互斥信号量(防止多任务同时进行内存申请时进行)

    (2)申请pre_alloc_size大小区域,用于1.(1),将每个内存块置为available。将整个内存块切分成 小内存块管理区域、大内存块管理区域、小内存块群、大内存块群 四个连续的区域。

    将小内存块群切成SMALLNUM个SMALLSIZE大小的内存单元,将大内存块群切成BIGNUM个BIGSIZE大小的内存单元。

    (3)初始化管理从堆申请的链表。


    3.申请地址 两个相关函数 

    (1) mem_malloc中进行判断,用户需要的size字节大小内存从 小内存区域、大内存区域和堆内存区域 申请。(与大小和内存区域占用情况相关)

    (2) malloc_by_type从已经判断好的区域进行申请,每次占用一块完整的内存。如用户需要一块小于SMALLSIZE字节的内存块,实际占用的也还是SMALLSIZE字节。用牺牲内部碎片的方法减少外部碎片。


    4.通过用户输入的首地址释放内存 mem_free()

    (1) 通过大、小内存块管理区域使用for循环,遍历是否有 内存块的首地址 与 用户想要释放的首地址一致,有则释放,并更新内存管理区域的数据。

    (2) 大、小内存块中未搜到,搜索 从堆申请的内存地址链 是否有该地址,有则释放,并且!释放存储该地址信息的结点。

    (3) 均未搜到,该地址为无效首地址。

    5.查看内存占用情况 mem_show()

    (1) 通过大、小内存管理区域的值,展示内存占用情况。

    (2) 遍历从堆申请的地址链表,展示内存占用情况。traverse_list()


    6.退出程序时,释放包含大小内存块的pre_alloc_size大小部分区域,释放堆申请地址链。


    7.将信号量相关部分注释掉后,可通过Dev C++等编译。查看一下效果↓



    代码地址  https://github.com/crab0314/vxworks_mem

    展开全文
  • 分页内存管理

    千次阅读 2019-03-18 16:31:41
    3、虚拟地址的构成与地址翻译4、页表5、分页内存管理的优缺点二、分页内存管理例子解析三、缺页中断和页面置换的目标1、缺页中断2、页面置换的目标四、页面置换算法1、最佳置换算法(OPT)2、最近最久未使用(LRU)3...

    一、分页内存管理详解

    1、分页内存管理的核心思想

      固定分区会产生内部碎片,动态分区会产生外部碎片,这两种技术对内存的利用率都比较低。我们希望内存的使用能尽量避免碎片的产生,这就引入了分页的思想:将虚拟内存空间和物理内存空间皆划分为大小相同的页面,如4KB、8KB或16KB等,并以页面作为内存空间的最小分配单位,一个程序的一个页面可以存放在任意一个物理页面里。

      分页的最大作用就在于:使得进程的物理地址空间可以是非连续的。

    2、分页内存管理能解决什么问题?

    • 解决空间浪费碎片化问题(外部碎片):由于将虚拟内存空间和物理内存空间按照某种规定的大小进行分配,这里我们称之为页(Page),然后按照页进行内存分配,也就克服了外部碎片的问题。

    • 解决程序大小受限问题:程序增长有限是因为一个程序需要全部加载到内存才能运行,因此解决的办法就是使得一个程序无须全部加载就可以运行。使用分页也可以解决这个问题,只需将当前需要的页面放在内存里,其他暂时不用的页面放在磁盘上,这样一个程序同时占用内存和磁盘,其增长空间就大大增加了。而且,分页之后,如果一个程序需要更多的空间,给其分配一个新页即可(而无需将程序倒出倒进从而提高空间增长效率)。

    3、虚拟地址的构成与地址翻译

    【虚拟地址的构成】:

      在分页系统下,一个程序发出的虚拟地址由两部分组成:页面号和页内偏移值,如下图所示:
    在这里插入图片描述
    例如,对于32位寻址的系统,如果页面大小为4KB,则页面号占20位,页内偏移值占12位。

    【地址翻译:虚拟地址→物理地址】:

      分页系统的核心是页面的翻译,即从虚拟页面到物理页面的映射(Mapping)。而这个翻译过程由内存管理单元(MMU)完成,MMU接收CPU发出的虚拟地址,将其翻译为物理地址后发送给内存。内存管理单元按照该物理地址进行相应访问后读出或写入相关数据,如下图所示:
    在这里插入图片描述
      那么,这个翻译是怎么实现的呢?答案是查页表,对于每个程序,内存管理单元MMU都为其保存一个页表,该页表中存放的是虚拟页面到物理页面的映射。每当为一个虚拟页面寻找到一个物理页面之后,就在页表里增加一条记录来保留该映射关系。当然,随着虚拟页面进出物理内存,页表的内容也会不断更新变化。
    在这里插入图片描述

    4、页表

      页表的根本功能是提供从虚拟页面到物理页面的映射。因此,页表的记录条数与虚拟页面数相同。此外,内存管理单元依赖于页表来进行一切与页面有关的管理活动,这些活动包括判断某一页面号是否在内存里,页面是否受到保护,页面是否非法空间等等。
    在这里插入图片描述
      页表的存储方式是TLB(Translation look-aside buffer, 转换表缓冲区)+内存。TLB实际上是一组硬件缓冲所关联的快速内存。若没有TLB,操作系统需要两次内存访问来完成逻辑地址到物理地址的转换,访问页表算一次,在页表中查找算一次。TBL中存储页表中的一小部分条目,条目以键值对方式存储。

    5、分页内存管理的优缺点

    【优点】:

    • 分页系统不会产生外部碎片一个进程占用的内存空间可以不是连续的,并且一个进程的虚拟页面在不需要的时候可以放在磁盘中。

    • 分页系统可以共享小的地址,即页面共享。只需要在对应给定页面的页表项里做一个相关的记录即可。

    【缺点】:

    • 页表很大,占用了大量的内存空间

    • 还是会存在内部碎片。

    二、分页内存管理例子解析

      把物理内存,按照某种尺寸,进行平均分割。比如我现在以2个内存单位,来分割内存,也就是每两个连续的内存空间,组成一个内存页:
    在这里插入图片描述
      接着,系统同样需要维护一个内存信息表:
    在这里插入图片描述
      现在,程序申请长度为3的内存空间,不过由于现在申请的最小单位为页面,而一个页面的长度为2,因此现在需要申请2个页面,也就是4个内存空间。这就浪费了1个内存空间。接着,程序再申请长度为1,长度为2的空间:
    在这里插入图片描述
      释放掉ID=2,内存页ID为3的那条内存空间信息:
    在这里插入图片描述
      现在,就出现了之前的情况:目前一共有4个内存空间,但是不连续。不过,因为现在是分页管理机制,因此,现在仍然可以继续申请长度为4的内存空间:
    在这里插入图片描述

    三、缺页中断和页面置换的目标

    1、缺页中断

      在分页系统中,一个虚拟页面既有可能在物理内存,也有可能保存在磁盘上。如果CPU发出的虚拟地址对应的页面不在物理内存,就将产生一个缺页中断,而缺页中断服务程序负责将需要的虚拟页面找到并加载到内存。
    在这里插入图片描述

    2、页面置换的目标

      如果发生了缺页中断,就需要从磁盘上将需要的页面调入内存。如果内存没有多余的空间,就需要在现有的页面中选择一个页面进行替换。使用不同的页面置换算法,页面更换的顺序也会各不相同。如果挑选的页面是之后很快又要被访问的页面,那么系统将很开再次产生缺页中断,因为磁盘访问速度远远内存访问速度,缺页中断的代价是非常大的。因此,挑选哪个页面进行置换不是随随便便的事情,而是有要求的。

      页面置换时挑选页面的目标主要在于降低随后发生缺页中断的次数或概率(也可以说缺页率最低)。因此,挑选的页面应当是随后相当长时间内不会被访问的页面,最好是再也不会被访问的页面

    四、页面置换算法

    1、最佳置换算法(OPT)

      所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率。是一种理论上的算法,因为无法知道一个页面多长时间不再被访问。

    2、最近最久未使用(LRU)

      虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近一段时间最久未使用的页面换出。

      为了实现 LRU,需要在内存中维护一个所有页面的链表当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。当发生缺页中断时,删除链表尾部最久没有使用的页面。

    在这里插入图片描述
      因为每次访问都需要更新链表,因此这种方式实现的 LRU 代价很高。

    3、最近未使用(NRU)

      每个页面都有两个状态位:R 与 M,当页面被访问时设置页面的 R=1,当页面被修改时设置 M=1。其中 R 位会定时被清零。可以将页面分成以下四类:

    • R=0,M=0
    • R=0,M=1
    • R=1,M=0
    • R=1,M=1

      当发生缺页中断时,NRU 算法随机地从类编号最小的非空类中挑选一个页面将它换出。

    4、先进先出(FIFO)

      顾名思义,先进先出(FIFO,First In First Out)算法的核心是更换最早进入内存的页面,其实现机制是使用链表将所有在内存中的页面按照进入时间的早晚链接起来,然后每次置换链表头上的页面就行了,而新加进来的页面则挂在链表的末端,如下图所示:
    在这里插入图片描述
      FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问题,对该算法做一个简单的修改:

      当页面被访问 (读或写) 时设置该页面的 R 位为 1。需要替换的时候,检查最老页面的 R 位。如果 R 位是 0,那么这个页面既老又没有被使用,可以立刻置换掉;如果是 1,就将 R 位清 0,并把该页面放到链表的尾端,修改它的装入时间使它就像刚装入的一样,然后继续从链表的头部开始搜索。
    在这里插入图片描述

    5、时钟

      时钟算法的核心思想是:将页面排成一个时钟的形状,该时钟有一个指针,每次需要更换页面时,我们从指针所指的页面开始检查如果当前页面的访问位为0,即从上次检查到这次,该页面没有被访问过,将该页面替换反之,就将其访问位清零,并顺时针移动指针到下一个页面。重复这些步骤,直到找到一个访问位为0的页面。

      例如下图所示的一个时钟,指针指向的页面是F,因此第一个被考虑替换的页面是F。如果页面F的访问位为0,F将被替换。如果F的访问位为1,则F的访问位清零,指针移动到页面G。
    在这里插入图片描述

    参考:https://blog.csdn.net/tong5956/article/details/74937178
    https://www.cnblogs.com/edisonchou/p/5094066.html

    展开全文
  • 引言:在前面几篇笔记中,我们介绍到内存管理的多种方式,包括单道编程下固定加载地址,多道编程下固定分区、非固定分区、分页式内存管理,这些是内存管理模式不断演进的过程,本篇笔记将介绍现今广泛使用的段页式...
  • 基本分段内存管理的引入引入分页内存管理方式的目的是提高内存空间利用率,而引入分段内存管理目的是满足程序员在编程和使用上的多方面要求: 方便编程:用户可以把自己的作业按照逻辑关系划分为若干个段,而且每...
  • Android内存管理

    千次阅读 2017-04-25 10:31:30
    Android 内存管理主要包括两个方面,一是系统级内存管理,二是应用级内存管理,下面将分别介绍这两方面内容。 一、Android系统级内存管理  系统级别内存管理是以进程为粒度进行管理,下面以进程为粒度,...
  • Redis内存管理

    千次阅读 2018-07-15 17:23:37
    Redis通过控制内存上限和回收策略实现内存管理,使用maxmemory参数限制最大可用内存,限制内存的主要目的是:用于缓存场景,当超出内存上限时使用LRU等删除策略释放空间;防止所用内存超过服务器的物理内存。内存...
  • C语言的内存管理机制

    2021-01-27 11:39:40
    内存管理目的。更多内容请看下文。 文章来自于csdn,由火龙果Anna编辑推荐。内存资源是非常有限的。尤其对于移动端开发者来说,硬件资源的限制使得其在程序设计中首要考虑的问题就是如何有效地管理内存资源。...
  • 主要涉及操作系统的物理内存管理。 操作系统为了使用内存,还需高效地管理内存资源。 这里我们会了解并且自己动手完成一个简单的物理内存管理系统。 实验目的 理解基于段页式内存地址的转换机制 理解...
  • 内存管理模型理解

    2017-01-12 14:37:36
    1 内存管理以stm32 f407开发板一个简单内存管理实例(分块式内存管理)进行说明,主要目的是理解内存管理的基本原理与实现方式,在其他很多系统中,都有更复杂高效的内存管理算法,可在后续工作中深入学习。...
  • Android 内存管理机制

    千次阅读 2018-09-03 14:41:45
    内存管理基础:从整个计算机领域简述主要内存管理技术。 Linux的内存管理机制:Android毕竟是基于Linux内核实现的操作系统,因此有必要了解一下Linux的内存管理机制。 Android的内存管理相关知识:Android又...
  • 内存寻址 、硬件中的分段与分页 、Linux内存管理 页与内存管理区 、kmalloc()和vmalloc()
  • STM32内存管理

    千次阅读 2019-03-15 15:28:43
    其最主要目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。 内存管理的实现方法有很多种,他们其实最终都是要实现 2 个函数: malloc 和 free; malloc 函数用于内存申请, free 函数用于内存...
  • Spark内存管理系列文章: Spark内存管理(1)—— 静态内存管理 Spark内存管理(2)—— 统一内存管理 在本文中,将会对各个内存的分布以及设计原理进行详细的阐述 相对于静态内存模型(即Storage和Execution...
  • 日期 内核版本 架构 作者 GitHub ... Linux内存管理内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到
  • Linux内存管理

    万次阅读 2015-03-12 16:55:39
    这是Linux内存管理的一个优秀特性,在这方面,区别于Windows的内存管理主要特点是,无论物理内存有多大,Linux 都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的...
  • 内存管理笔记五、固定分区的多道编程 引言:多道编程可以克服单道编程的缺点,提高CPU和内存的利用效率,改善用户的响应时间。本文将介绍多道编程下固定分区的内存管理。后续文章会介绍非固定分区、分页、分段、段...
  • Java内存管理

    万次阅读 多人点赞 2016-03-08 21:36:06
    不过看了一遍《深入Java虚拟机》再来理解Java内存管理会好很多。接下来一起学习下Java内存管理吧。请注意上图的这个:我们再来复习下进程与线程吧:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,...
  • Java 内存管理

    千次阅读 2016-11-21 01:52:14
    弄清JVM(Java Virtual Machine)的内存管理模型对了解Java GC工作原理是很有必要的。本文介绍Java内存管理的处理方式,包括JVM内存分配各个区域的含义,以及如何监测协调GC工作。
  • Spark内核之内存管理

    千次阅读 2020-09-17 22:36:30
    2.1 早期内存管理(静态内存管理) 2.2 统一内存管理 2.3 同一管理内存的优点 三、存储内存管理 3.1 RDD的持久化机制 3.2RDD的缓存过程 3.3 淘汰与落盘 四、执行内存管理 4.1 Shuffle Write 4.2 Shuffle ...
  • Linux内存管理机制

    千次阅读 2017-02-16 04:07:24
    这是Linux内存管理的一个优秀特性,主要特点是,无论物理内存有多大,Linux 都将其充份利用,将一些程序调用过的硬盘数据读入内存(buffer/cache),利用内存读写的高速特性来提高Linux系统的数据访问性能。...
  • Linux内存管理介绍

    2014-12-08 21:04:06
    内存管理目标: 提供一种方法,在各种目的各个用户之间实现内存共享,应该实现以下两个功能: 1、最小化管理内存的时间,内存申请和释放响应时间短 2、最优化用于一般应用的可用内存,内存管理(算法)所占用的内存...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 602,573
精华内容 241,029
关键字:

内存管理的主要目的是