精华内容
下载资源
问答
  • 原创作者:ilovefei.fei 出自: http://www.linuxdiyf.com这么长时间来,我一直在尝试不同版本的linux和不同版本的windows,总体感觉下来,windows内存管理机制要强于linux,首先是从这两种系统的反应速度上看的。...

    原创作者:ilovefei.fei 出自: http://www.linuxdiyf.com

    这么长时间来,我一直在尝试不同版本的linux和不同版本的windows,总体感觉下来,windows的内存管理机制要强于linux,首先是从这两种系统的反应速度上看的。

    不管是那一个linux版本,总体上来说,他们的速度没有windows反应快!是为什么呢?是系统过于庞大吗?不是,linux装下来就是8个g左右,而xp和vista居于其上下。这样,linux过于庞大就不是什么理由了。

    不知道别人会怎么解释这个问题,但是在我细细想来,就是认为linux的内存管理机制不好。为什么要把一堆东西先放到内存里面?这样真正的快吗?如果这样可以解决硬件之间的速度不同步的问题,哪么为什么还要用一个swap分区呢?这是完全没有必要的!有人说这正是为了加快linux的响应速度。这也不叫理由!你把所有的内存都占完了,哪么接下来如果要运行一个大软件怎么办呢?内存从哪里透支呢?我没有深入的研究,总体感觉下来,响应速度没有比vista快多少!甚至没有快!

    或许有人说,linux主要是用于具有强大硬件的服务器的,但是,为什么现在这么多人在追捧linux用于桌面领域呢?如果是要用于桌面领域,linux是太不合适了。

    当然,本篇讨论的完全忽略了操作系统的价格问题。

    若有错误指出,恳请指正。

    展开全文
  • 文章目录为什么使用虚拟内存分配虚拟内存Windows内存管理APIVirtualAllocVirtualProtectVirtualFreeC++代码 为什么使用虚拟内存 虚拟内存最适合用来管理大型对象或数据结构。 比如说,电子表格程序,有很多单元格,...

    为什么使用虚拟内存

    虚拟内存最适合用来管理大型对象或数据结构。

    比如说,电子表格程序,有很多单元格,但是也许大多数的单元格是没有数据的,用不着分配空间。也许,你会想到用动态链表,但是访问又没有数组快。定义二维数组,就会浪费很多空间。

    它的优点是同时具有数组的快速和链表的小空间的优点。


    分配虚拟内存

    如果你程序需要大块内存,你可以先保留内存,需要的时候再提交物理存储器。在需要的时候再提交才能有效的利用内存。一般来说,如果需要内存大于1M,用虚拟内存比较好。


    Windows内存管理API

    VirtualAlloc

    在调用进程的虚拟地址空间中保留、提交或更改页面区域的状态。此函数分配的内存会自动初始化为零。
    参数

    [in, optional] LPVOID lpAddress,        //开始地址
    [in]           SIZE_T dwSize,           //大小
    [in]           DWORD  flAllocationType, //类型
    [in]           DWORD  flProtect         //保护属性
    
    • lpAddress:要分配的区域的起始地址。
      一般情况下,你不需要指定“开始地址”,因为你不知道进程的那段空间是不是已经被占用了;所以你可以用NULL。
    • dwSize:区域的大小,以字节为单位。
    • flAllocationType:
      “类型”有
      MEM_RESERVE(保留)保留区域不占用任何物理存储。
      MEM_RELEASE(释放)
      MEM_COMMIT(提交)为指定的保留内存页面分配内存费用
      如果你要保留的是长久不会释放的内存区,就保留在较高的空间区域,这样不会产生碎片。用这个类型标志可以达到:
      MEM_RESERVE|MEM_TOP_DOWN。
    • flProtect:要分配的页面区域的内存保护。

    返回值
    如果函数成功,则返回值是页面分配区域的基地址。

    如果函数失败,则返回值为NULL。要获取扩展错误信息,请调用GetLastError。

    VirtualProtect

    更改对调用进程虚拟地址空间中已提交页面区域的保护。
    参数

    [in]  LPVOID lpAddress,
    [in]  SIZE_T dwSize,
    [in]  DWORD  flNewProtect,  //新属性
    [out] PDWORD lpflOldProtect //旧属性
    

    返回值
    如果函数成功,则返回值非零。

    如果函数失败,则返回值为零。要获取扩展错误信息,请调用 GetLastError。

    VirtualFree

    调用进程的虚拟地址空间内释放、取消提交或释放和取消提交页面区域。
    参数

    [in] LPVOID lpAddress,  //指向要释放的页面区域的基地址的指针。
    [in] SIZE_T dwSize,     //要释放的内存区域的大小,以字节为单位。
    [in] DWORD  dwFreeType  //释放操作的类型。
    
    • dwFreeType类型
      MEM_DECOMMIT 取消提交页面的指定区域。操作后,页面处于保留状态。
      MEM_RELEASE 释放指定的页面区域或占位符(对于占位符,地址空间被释放并可用于其他分配)。此操作后,页面处于空闲状态。

    返回值
    如果函数成功,则返回值非零。

    如果函数失败,则返回值为 0(零)。要获取扩展错误信息,请调用 GetLastError


    C++代码

    自定义内存状况输出函数

    void printMemStatus()
    {
        MEMORYSTATUS memStatusVirtual;
        GlobalMemoryStatus(&memStatusVirtual);
        cout << "dwAvailPhys :"<<memStatusVirtual.dwAvailPhys/1024/1024<<"MB"<<endl;
        cout << "dwAvailPageFile :"<<memStatusVirtual.dwAvailPageFile/1024/1024<<"MB"<<endl;
        cout << "dwAvailVirtual :"<<memStatusVirtual.dwAvailVirtual/1024/1024<<"MB"<<endl;
    }
    

    保留空间

    //输出内存保留前情况
    printMemStatus();
    
    //保留512mb的空间
    LPVOID pV=VirtualAlloc(NULL,512*1024*1024,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READWRITE); 
    if(pV==NULL){
        cout<<"VirtualAlloc MEM_RESERVE failed."<<endl; 
        return 0; 
    }
    
    cout<<"******************************"<<endl;
    cout<<"After VirtualAlloc MEM_RESERVE"<<endl;
    cout<<"******************************"<<endl;
    //输出保留后内存情况
    printMemStatus();
    

    在这里插入图片描述
    dwAvailVirtual 进程可用虚拟内存减少了512mb

    提交

    //提交 128mb 空间 
    LPVOID pP=VirtualAlloc(pV,128*1024*1024,MEM_COMMIT,PAGE_READWRITE);    
    if(pP==NULL){
        cout<<"VirtualAlloc MEM_COMMIT failed."<<endl;
        return 0;
    }
    cout<<"******************************"<<endl;
    cout<<"After VirtualAlloc MEM_COMMIT"<<endl;
    cout<<"******************************"<<endl;
    printMemStatus();
    

    在这里插入图片描述
    dwAvailPhys 实际物理内存减少了128mb
    修改页保护属性

    DWORD protect;
    VirtualProtect(pV, 1024*4, PAGE_READONLY,&protect) ;
    int * iP=(int*)pV;
    iP[1023] = 1; //报错,在这一页之中 
    iP[1024] = 1; //不报错 
    

    释放

    //只释放物理内存
    VirtualFree((int*)pV,100*1024*1024,MEM_DECOMMIT);
    cout<<"******************************"<<endl;
    cout<<"After VirtualFree MEM_DECOMMIT"<<endl;
    cout<<"******************************"<<endl;
    printMemStatus(); 
    //释放全部空间
    VirtualFree(pV,0,MEM_RELEASE); 
    cout<<"******************************"<<endl;
    cout<<"After VirtualFree MEM_RELEASE"<<endl;
    cout<<"******************************"<<endl;
    printMemStatus(); 
    

    完整代码

    #include <cstdio>
    #include <memoryapi.h>
    #include <Windows.h>
    #include <winbase.h> 
    #include <iostream> 
    using namespace std;
    void printMemStatus()
    {
    	MEMORYSTATUS memStatusVirtual;
    	GlobalMemoryStatus(&memStatusVirtual);
    	cout << "dwAvailPhys :"<<memStatusVirtual.dwAvailPhys/1024/1024<<"MB"<<endl;
        cout << "dwAvailPageFile :"<<memStatusVirtual.dwAvailPageFile/1024/1024<<"MB"<<endl;
        cout << "dwAvailVirtual :"<<memStatusVirtual.dwAvailVirtual/1024/1024<<"MB"<<endl;
    }
    int main()
    {
    	printMemStatus();
    	//保留512mb的空间
    	LPVOID pV=VirtualAlloc(NULL,512*1024*1024,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READWRITE); 
        if(pV==NULL){
        	cout<<"VirtualAlloc MEM_RESERVE failed."<<endl; 
        	return 0; 
    	}
        cout<<"******************************"<<endl;
        cout<<"After VirtualAlloc MEM_RESERVE"<<endl;
        cout<<"******************************"<<endl;
        printMemStatus();
    
    	//提交 128mb 空间 
    	LPVOID pP=VirtualAlloc(pV,128*1024*1024,MEM_COMMIT,PAGE_READWRITE);    
        if(pP==NULL){
        	cout<<"VirtualAlloc MEM_COMMIT failed."<<endl;
        	return 0;
    	}
    	cout<<"******************************"<<endl;
        cout<<"After VirtualAlloc MEM_COMMIT"<<endl;
        cout<<"******************************"<<endl;
    	printMemStatus();
        	
    	//更改页面保护属性 
        DWORD protect;
        VirtualProtect(pV, 1024*4, PAGE_READONLY,&protect) ;
        int * iP=(int*)pV;
        //iP[1023] = 1; //报错,在这一页之中 
        iP[1024] = 1; //不报错 
        
        
        //只释放100mb物理内存
        VirtualFree((int*)pV,100*1024*1024,MEM_DECOMMIT);
        cout<<"******************************"<<endl;
        cout<<"After VirtualFree MEM_DECOMMIT"<<endl;
        cout<<"******************************"<<endl;
        printMemStatus(); 
        //释放全部空间
    	VirtualFree(pV,0,MEM_RELEASE);
    	cout<<"******************************"<<endl;
        cout<<"After VirtualFree MEM_RELEASE"<<endl;
        cout<<"******************************"<<endl;
        printMemStatus(); 
    }
    

    在这里插入图片描述

    展开全文
  • Windows内存管理学习笔记(一)—— 线性地址的管理前言线性地址的管理用户空间实验:理解用户空间线性地址管理Private Memory实验:理解Private Memory堆 前言 一、学习自滴水编程达人中级班课程,官网:...

    用户空间线性地址的管理

    基本概念:每一个进程都有一个4GB的线性地址空间

    描述

    1. 每个进程都有自己的用户空间需要管理,当我们使用VirtualAlloc等函数申请一块固定的地址空间时,首先需要确认这块空间是否被占用,如果该空间已被占用则申请失败
    2. 用户空间并非像内核空间一样通过一块链表去管理已占用的线性地址空间(效率低), 而是通过搜索二叉树

    申请内存的两种方式

    1. 通过VirtualAlloc/VirtualAllocEx申请:Private Memory(独享物理页)
    2. 通过CreateFileMapping进行映射:Mapped Memory(共享物理页)

    进程空间地址划分
    在这里插入图片描述
    注意:
    1)只有用户模式区是用户能够访问的
    2)所谓的“无法访问”只是目标地址没有被挂上有效的物理页(详见保护模式章节)
    3)通常,当我们需要申请一块内存时,通过系统提供的API去申请
    4)当我们申请一块内存时,系统需要对这块内存做记录,表示它已经被申请了,之后再进行申请时,系统就不会再分配这块地址给我们了
    5)在内核层,通过一块链表,将所有未进行分配的空间的地址串起来,当我们需要分配空间时,在这一块链表中寻找
    6)内核空间线性地址管理相对简单(参考《Windows内核原理与实现》)
    7)本章主要介绍用户空间线性地址管理(相对复杂)

    实验一:理解用户空间线性地址管理

    1)使用WinDbg查看进程列表

    命令:!process 0 0

    2)定位一个exe程序
    在这里插入图片描述
    3)查看EPROCESS结构体

    命令:dt _EPROCESS 86360440

    ntdll!_EPROCESS
       ......
       +0x11c VadRoot          : 0x8656ef48 Void		//入口点,进去后是搜索二叉树
       													//每一个节点记录了一块已被占用的线性地址空间
       													//对应_MMVAD结构体
       ......
    

    4)查看MMVAD结构体

    命令:dt _MMVAD 0x8656ef48

    nt!_MMVAD
       +0x000 StartingVpn      : 0x400				//重要,以页为单位,后面添上三个0即是当前节点所描述的线性地址的起始位置
       +0x004 EndingVpn        : 0x42b				//重要,以页为单位,后面添上三个0即是当前节点所描述的线性地址的结束位置
       +0x008 Parent           : (null) 			//根节点,不存在父节点
       +0x00c LeftChild        : 0x86237d60 _MMVAD	//左子树
       +0x010 RightChild       : 0x863e6a20 _MMVAD	//右子树
       +0x014 u                : __unnamed			//对应_MMVAD_FLAGS结构体
       +0x018 ControlArea      : 0x86610220 _CONTROL_AREA	//包含该节点所对应的线性地址被谁占用等信息
       +0x01c FirstPrototypePte : 0xe11e1048 _MMPTE
       +0x020 LastContiguousPte : 0xfffffffc _MMPTE
       +0x024 u2               : __unnamed
    

    5)查看CONTROL_AREA结构体

    命令:dt _CONTROL_AREA 0x86610220

    nt!_CONTROL_AREA
       +0x000 Segment          : 0xe11e1008 _SEGMENT
       +0x004 DereferenceList  : _LIST_ENTRY [ 0x0 - 0x0 ]
       +0x00c NumberOfSectionReferences : 1
       +0x010 NumberOfPfnReferences : 0x13
       +0x014 NumberOfMappedViews : 1
       +0x018 NumberOfSubsections : 6
       +0x01a FlushInProgressCount : 0
       +0x01c NumberOfUserReferences : 2
       +0x020 u                : __unnamed
       +0x024 FilePointer      : 0x863219d0 _FILE_OBJECT	//若为空,表示线性地址指向真正的物理页
       +0x028 WaitingForDeletion : (null) 
       +0x02c ModifiedWriteCount : 0
       +0x02e NumberOfSystemCacheViews : 0
    

    6)查看FILE_OBJECT结构体

    命令:dt _FILE_OBJECT 0x863219d0

    ntdll!_FILE_OBJECT
       ......
       +0x030 FileName         : _UNICODE_STRING "\Documents and Settings\User\桌面\test\Debug\test.exe"
       							//线性地址属于主模块
       ......
    

    7)查看MMVAD_FLAGS结构体

    命令:kd> dt _MMVAD_FLAGS 86237d60+0x14

    nt!_MMVAD_FLAGS
       +0x000 CommitCharge     : 0y0000000000000000111 (0x7)
       +0x000 PhysicalMapping  : 0y0
       +0x000 ImageMap         : 0y1	//为1表示镜像文件(可执行文件),0表示其他
       +0x000 UserPhysicalPages : 0y0
       +0x000 NoChange         : 0y0
       +0x000 WriteWatch       : 0y0
       +0x000 Protection       : 0y00111 (0x7)	//表示内存权限为EXECUTE_WRITECOPY
       +0x000 LargePages       : 0y0
       +0x000 MemCommit        : 0y0
       +0x000 PrivateMemory    : 0y0	//0表示Mapped Memory
    

    8)遍历所有节点

    命令:!vad 0x8656ef48

    VAD   Level     Start       End Commit
    86237d60  1        10        10      1 Private      READWRITE          
    85e1adc0  2        20        20      1 Private      READWRITE          
    866df830  3        30       12f      3 Private      READWRITE          
    86320ac0  4       130       132      0 Mapped       READONLY           Pagefile section, shared commit 0x3
    86425598  5       140       23f      4 Private      READWRITE          
    867c49d0  6       240       24f      6 Private      READWRITE          
    862ff800  7       250       25f      0 Mapped       READWRITE          Pagefile section, shared commit 0x3
    864bcad8  8       260       275      0 Mapped       READONLY           \WINDOWS\system32\unicode.nls
    86348070  9       280       2c0      0 Mapped       READONLY           \WINDOWS\system32\locale.nls
    863ec958 10       2d0       310      0 Mapped       READONLY           \WINDOWS\system32\sortkey.nls
    86673f10 11       320       325      0 Mapped       READONLY           \WINDOWS\system32\sorttbls.nls
    85dd0b40 12       330       370      0 Mapped       READONLY           Pagefile section, shared commit 0x41
    86425fe8 13       380       38f      5 Private      READWRITE          
    86588948 14       390       392      0 Mapped       READONLY           \WINDOWS\system32\ctype.nls
    8656ef48  0       400       42b      7 Mapped  Exe  EXECUTE_WRITECOPY  \Documents and Settings\JinXiangcheng\桌面\test\Debug\test.exe
    862664c0  2     7c800     7c91d      5 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\kernel32.dll
    863e6a20  1     7c920     7c9b2      5 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\ntdll.dll
    862f4cb0  3     7f6f0     7f7ef      0 Mapped       EXECUTE_READ       Pagefile section, shared commit 0x7
    8633aa60  2     7ffa0     7ffd2      0 Mapped       READONLY           Pagefile section, shared commit 0x33
    8648b448  3     7ffdb     7ffdb      1 Private      READWRITE          
    86244d88  4     7ffdf     7ffdf      1 Private      READWRITE          
    
    Total VADs: 21, average level: 6, maximum depth: 14
    Total private commit: 0x27 pages (156 KB)
    Total shared commit:  0x81 pages (516 KB)
    

    总结:
    1)所有的线性地址空间是需要管理的(哪些地址是占用的,哪些地址是未占用的)
    2)所有用户线性地址空间通过搜索二叉树进行管理(占用大小占用方式内存属性
    4)所有已占用的线性地址可以分为两类

    1. VirtualAlloc分配的普通内存
    2. 文件映射(Mapped)的内存(例如dll/exe/txt等)

    5)传统的模块隐藏技术,终究会在VadRoot中留下痕迹,假设摘除,操作系统会误认为该地址空间未被分配,从而产生非预期中的错误

    Private Memory

    描述:通过VirtualAlloc/VirtualAllocEx申请的内存,叫做Private Memory

    LPVOID VirtualAlloc{
    	LPVOID lpAddress, 		// 要分配的内存区域的地址,填0则随机分配一块符合条件的地址
    	DWORD dwSize, 			// 分配的大小,4kb对齐
    	DWORD flAllocationType, 	// 分配的类型
    							// MEM_RESERVE:只保留线性地址,不分配物理页
    							// MEM_COMMIT:既保留线性地址,又分配物理页
    	DWORD flProtect 			// 该内存的初始保护属性
    };
    

    实验二:理解Private Memory

    1)编译并运行以下代码

    #include <stdio.h>
    #include <windows.h>
    
    LPVOID lpAddress;
    
    int main()
    {
    	printf("程序运行了...内存还没有申请\n");
    	getchar();
    
    	lpAddress = VirtualAlloc(NULL, 0x1000*2, MEM_COMMIT, PAGE_READWRITE);
    	printf("内存地址:%x\n", lpAddress);
    
    	getchar();
    	return 0;
    }
    

    在这里插入图片描述

    2)遍历VadRoot

    kd> !process 0 0
    **** NT ACTIVE PROCESS DUMP ****
    ......
    Failed to get VadRoot
    PROCESS 86498ca0  SessionId: 0  Cid: 026c    Peb: 7ffd3000  ParentCid: 0b80
        DirBase: 0e800380  ObjectTable: e2abfd10  HandleCount:  18.
        Image: test.exe
    
    kd> dt _EPROCESS 86498ca0  
    ntdll!_EPROCESS
       ......
       +0x11c VadRoot          : 0x86543ed8 Void
       ......
    
    kd> !vad 0x86543ed8 
    VAD   Level     Start       End Commit
    8621f160  1        10        10      1 Private      READWRITE          
    866d04e0  2        20        20      1 Private      READWRITE          
    86591aa8  3        30       12f      3 Private      READWRITE          
    862f9658  4       130       132      0 Mapped       READONLY           Pagefile section, shared commit 0x3
    865d7920  5       140       23f      3 Private      READWRITE          
    85decda0  6       240       24f      6 Private      READWRITE          
    862d7068  7       250       25f      0 Mapped       READWRITE          Pagefile section, shared commit 0x3
    862df620  8       260       275      0 Mapped       READONLY           \WINDOWS\system32\unicode.nls
    85e009d0  9       280       2c0      0 Mapped       READONLY           \WINDOWS\system32\locale.nls
    85e4b6b0 10       2d0       310      0 Mapped       READONLY           \WINDOWS\system32\sortkey.nls
    86588988 11       320       325      0 Mapped       READONLY           \WINDOWS\system32\sorttbls.nls
    865e7bb8 12       330       370      0 Mapped       READONLY           Pagefile section, shared commit 0x41
    8642b528 13       380       38f      5 Private      READWRITE          
    8665e1b0 14       390       392      0 Mapped       READONLY           \WINDOWS\system32\ctype.nls
    86543ed8  0       400       42c      8 Mapped  Exe  EXECUTE_WRITECOPY  \Documents and Settings\JinXiangcheng\桌面\test\Debug\test.exe
    865feaf8  2     7c800     7c91d      5 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\kernel32.dll
    85df5180  1     7c920     7c9b2      5 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\ntdll.dll
    86487da0  3     7f6f0     7f7ef      0 Mapped       EXECUTE_READ       Pagefile section, shared commit 0x7
    863b1100  2     7ffa0     7ffd2      0 Mapped       READONLY           Pagefile section, shared commit 0x33
    863ef410  3     7ffd3     7ffd3      1 Private      READWRITE          
    8640f148  4     7ffdf     7ffdf      1 Private      READWRITE          
    
    Total VADs: 21, average level: 6, maximum depth: 14
    Total private commit: 0x27 pages (156 KB)
    Total shared commit:  0x81 pages (516 KB)
    

    3)继续运行程序,查看分配到的地址
    在这里插入图片描述
    4)再次遍历VadRoot,观察变化

    kd> !vad 0x86543ed8 
    VAD   Level     Start       End Commit
    862f9658  2       130       132      0 Mapped       READONLY           Pagefile section, shared commit 0x3
    865d7920  1       140       23f      3 Private      READWRITE          
    85decda0  3       240       24f      6 Private      READWRITE          
    862d7068  2       250       25f      0 Mapped       READWRITE          Pagefile section, shared commit 0x3
    862df620  4       260       275      0 Mapped       READONLY           \WINDOWS\system32\unicode.nls
    85e009d0  3       280       2c0      0 Mapped       READONLY           \WINDOWS\system32\locale.nls
    85e4b6b0  5       2d0       310      0 Mapped       READONLY           \WINDOWS\system32\sortkey.nls
    86588988  4       320       325      0 Mapped       READONLY           \WINDOWS\system32\sorttbls.nls
    865e7bb8  6       330       370      0 Mapped       READONLY           Pagefile section, shared commit 0x41
    8642b528  5       380       38f      5 Private      READWRITE          
    8665e1b0  6       390       392      0 Mapped       READONLY           \WINDOWS\system32\ctype.nls
    ---------------------------------------------------------------------
    86600dc0  7       3a0       3a1      2 Private      READWRITE	//新增节点
    ---------------------------------------------------------------------
    86543ed8  0       400       42c      8 Mapped  Exe  EXECUTE_WRITECOPY  \Documents and Settings\JinXiangcheng\桌面\test\Debug\test.exe
    865feaf8  2     7c800     7c91d      5 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\kernel32.dll
    85df5180  1     7c920     7c9b2      5 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\ntdll.dll
    86487da0  3     7f6f0     7f7ef      0 Mapped       EXECUTE_READ       Pagefile section, shared commit 0x7
    863b1100  2     7ffa0     7ffd2      0 Mapped       READONLY           Pagefile section, shared commit 0x33
    863ef410  3     7ffd3     7ffd3      1 Private      READWRITE          
    8640f148  4     7ffdf     7ffdf      1 Private      READWRITE          
    
    Total VADs: 19, average level: 4, maximum depth: 7
    Total private commit: 0x24 pages (144 KB)
    Total shared commit:  0x81 pages (516 KB)
    

    描述

    1. 堆是操作系统提前通过VirtualAlloc/VirtualAllocEx申请的一块内存,存在于VadRoot
    2. 在C++中,若是想创建一个对象,需要用到new,此时,会在堆中创建一个对象,new的底层实现就是malloc,malloc的底层都是通过HeapAlloc实现的,HeapAlloc要做的事就是在堆中分配一块内存
    3. 简而言之,操作系统“批发”了一块很大的内存,无论是通过malloc还是new申请的内存,本质上都是从这块内存中“零售”出了一小块
    4. malloc的底层并没有进0环,因此系统并没有分配出一块新的内存(跟踪malloc实现得知)
    5. 只有当使用VirtualAlloc/VirtualAllocEx或者Mapped时,才会分配出一块新的内存

    实验三:理解堆

    1)编译并运行以下代码(在首行设置断点)

    #include <stdio.h>
    #include <windows.h>
    
    int x = 0x1234;
    
    int main()
    {
    	int y = 0x5678;
    	int *z = (int*)malloc(sizeof(int)*128);
    
    	printf("全局变量:%x\n", &x);
    	printf("栈:%x\n", &y);
    	printf("堆:%x\n", z);
    
    	getchar();
    	return 0;
    }
    
    

    2)查看当前进程的VadRoot
    在这里插入图片描述
    3)继续运行程序,观察结果
    在这里插入图片描述4)再次查看VadRoot,发现并无任何变化
    在这里插入图片描述
    结论:

    1. 在栈中定义变量或者通过malloc申请内存时,系统并没有新分配一块内存,而是从事先分配好的空间中划分出一小块
    2. 全局变量在编译代码时,地址已经被绑定在了可执行文件

    Mapped Memory

    描述
    1)通过CreateFileMapping映射的内存,叫做Mapped Memory,一个进程中大部分的内存都属于Mapped Memory
    2)Mapped Memory可以分为两类

    1. 共享内存:当内存为共享内存时,本质是共享一份物理页
    2. 共享文件:当内存为共享文件时,这块内存可能被映射到多个进程空间中,但真正占用的物理页只有一份

    3)无论是共享内存还是文件,在底层实现都是一样的,当我们需要共享物理页的时候,系统只需将物理页准备好,当我们需要共享文件时,系统先将物理页准备好,然后将物理页与文件进行关联

    实验四:理解共享内存

    1)编译并运行以下代码(进程A)

    #include <stdio.h>
    #include <windows.h>
    
    #define MapFileName "共享内存"
    
    int main()
    {
    	//内核对象:1.物理页	2. 文件
    	//准备一块内存,若第一个参数为INVALID_HANDLE_VALUE(-1)表示共享物理页
    	HANDLE g_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUFSIZ, MapFileName);
    
    	//将物理页与线性地址进行映射
    	LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);
    
    	*(PDWORD)g_lpBuff = 0x12345678;
    
    	printf("A进程写入地址,内容:%p - %x", g_lpBuff, *(PDWORD)g_lpBuff);
    
    	getchar();
    	return 0;
    }
    

    2)查看进程A的执行结果
    在这里插入图片描述
    3)查看进程A的VadRoot
    在这里插入图片描述
    4)保持进程A运行,编译并运行以下代码(进程B)

    #include <stdio.h>
    #include <windows.h>
    
    #define MapFileName "共享内存"
    
    int main()
    {
    	//内核对象:1.物理页	2. 文件
    	HANDLE g_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, MapFileName);
    
    	//将物理页与线性地址进行映射
    	LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);
    
    
    	printf("B进程读取地址,内容:%p - %x", g_lpBuff, *(PDWORD)g_lpBuff);
    
    	getchar();
    	return 0;
    }
    

    5)查看进程B执行结果
    在这里插入图片描述
    6)查看进程B的VadRoot
    在这里插入图片描述

    实验五:理解共享文件

    1)编译并运行以下代码(在return处设置断点)

    #include <stdio.h>
    #include <windows.h>
    
    int main()
    {
    	//内核对象:1.物理页	2. 文件
    	HANDLE g_hFile = CreateFile("C:\\NOTEPAD.EXE",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);	
    	
    	HANDLE g_hMapFile = CreateFileMapping(g_hFile,NULL,PAGE_READWRITE,0, BUFSIZ,NULL);
    
    	//将物理页与线性地址进行映射
    	LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);
    
    	return 0;
    }
    

    2)查看g_lpBuff的地址
    在这里插入图片描述
    3)查看当前进程的VadRoot
    在这里插入图片描述

    Mapped Exe

    描述

    1. 当一个程序通过LoadLibrary进行加载时,此时该文件所在的线性地址空间的属性为Mapped Exe权限为EXECUTE_WRITECOPY
    2. 由于权限为EXECUTE_WRITECOPY的地址空间是需要共享给所有程序使用的,因此当我们对权限为EXECUTE_WRITECOPY的线性地址空间的任何位置进行修改时,系统会先给这块内存重新映射一份物理页,然后再进行修改

    实验六:理解Mapped Exe

    1)编译并运行以下代码(在return处设置断点)

    #include <stdio.h>
    #include <windows.h>
    
    int main()
    {
    	HMODULE hModule = LoadLibrary("C:\\NOTEPAD.EXE");
    
    	return 0;
    }
    

    2)查看当前进程的VadRoot
    在这里插入图片描述

    总结

    1)线性地址分为三类:私有内存 | 共享内存 | 共享文件
    2)共享内存和共享文件本质相同,都是分配了一块物理页,不同的是共享文件将物理页和文件关联了起来
    3)传统的模块隐藏技术很难在VadRoot中进行隐藏(脱钩可能会导致程序崩溃),除非通过VirtualAlloc分配私有内存,手动将文件进行拉伸与贴入等一系列操作,此时能够大大增加寻找该模块的难度

    思考:当使用VirtualAlloc进行模块隐藏并且抹去特征时,如何找到这个模块?
    答案:内存搜索

    展开全文
  • Linux系统内存管理

    2021-05-11 11:28:58
    这正是Windows和Linux在内存管理上的区别,乍一看,Linux系统吃掉我们的内存(Linux ate my ram),但其实这也正是其内存管理的特点。下面为使用free命令查看结果$<2>$ free -mtotal used free...

    当我们使用free命令查看Linux系统内存使用情况时,会发现内存使用一直处于较高的水平,即使此时系统并没有运行多少软件。这正是Windows和Linux在内存管理上的区别,乍一看,Linux系统吃掉我们的内存(Linux ate my ram),但其实这也正是其内存管理的特点。

    下面为使用free命令查看结果

    $<2>$ free -m

    total      used      free    shared    buffers    cached

    Mem:          3834      2952        882          0          2      2096

    -/+ buffers/cache:        852      2981

    Swap:        3074        23      3051

    输出的第二行表示系统内存的使用情况:

    Mem: total(总量)= 3834MB,

    used(已使用)= 2952MB,

    free(空闲)= 882MB,

    shared(共享内存)= 0MB,

    buffers = 2MB,

    cached = 882MB

    注:前面四项都比较好理解,buffer 和 cache找不到合适的词来翻译,它们的区别在于:

    A buffer is something that has yet to be “written” to disk.

    A cache is something that has been “read” from the disk and stored for later use.

    即buffer用于存放要输出到磁盘的数据,而cache是从磁盘读出存放到内存中待今后使用的数据。这块内存从操作系统的角度确实被使用,但如果用户要使用,这块内存是可以很快被回收被用户程序使用,因此从用户角度这块内存应划为空闲状态。它们的引入均是为了提供IO的性能。

    输出的第三行表示在第二行的基础上-/+ buffers/cache得到的:

    – buffers/cache used = Mem used – buffers – cached = 2952MB – 2MB – 2096MB = 852MB

    + buffers/cache free = Mem free + buffers + cached = 882MB + 2MB + 2096MB = 2981MB

    操作系统把内存分为三部分:

    1、已经被应用使用部分。

    2、操作系统用来IO缓冲,可以被释放给应用使用部分。即free命令中”buffers/cached”的内存。

    3、未被使用部分。

    实验证明:dd if=/dev/zero of=bigfile bs=1M count=1000

    du -h bigfile

    echo 3 | tee /proc/sys/vm/drop_caches

    free -m

    time cat bigfile > /dev/null

    free -m

    time cat bigfile > /dev/null

    free -m

    展开全文
  • Windows内存管理学习笔记(三)—— 无处不在的缺页异常前言缺页异常实验一:设置虚拟内存 前言 一、学习自滴水编程达人中级班课程,官网:https://bcdaren.com 二、海东老师牛逼! 缺页异常 描述: 当CPU访问一...
  • 前言请说说你对windows/linux内存管理的认识解答内存管理的必要性出现在早期的计算机系统当中,程序是直接运行在物理内存中,每一个程序都能直接访问物理地址。如果这个系统只运行一个程序的话,并且这个程序所需的...
  • 这表示显卡内存不足,搜索怎么释放显卡的内存的时候,大多都是linux下的解决方法windows下可以这样做:打开cmd窗口,输入nvidai-smi查看显卡使用情况如图 可以看到下边有个PID表示进程id,然后打开任务管理器,...
  • 您好,我们了解到您开机后Windows 资源管理器(explorer.exe)占用内存问题。请问您在这之前有任何的操作过现象吗?例如优化或者清理、删除、更新、安装等等操作。建议您在任务管理器中先结束Windows 资源管理器进程,...
  • Linux?系统和android?虽然都是用的是linux内核,但对处理程序内存方式不一样,特别是前台的上层程序,内核级程序基本是一样的。...而windows的处理方式是?内存和虚拟内存一起使用,不是以内存操作为主,这样的...
  • windows任务管理器中的工作设置内存,内存专用工作集,提交大小详解 虽然是中文字,但是理解起来还是很困难,什么叫工作设置内存,什么叫内存专用工作集,什么叫提交大小,区别是什么,让人看了一头雾水. 通俗的讲工作...
  • 【填空题】代码 for i in range(3):print(i, end=’,’) 【填空题】已知列表 x = [1, 2],那么连续执行命令 y = x和 y.append(3) 之后,x的值为 【判断题】Python采用的是基于值得自动内存管理方式。 【判断题】Python...
  • windows内存诊断工具有什么简便的处理方式呢,其实只要依照1、首先在win7纯净版32位系统下我们打开“开始——控制面板”,接着大家把“控制面板”里的“查看方式”直接设置成“大图标”状态,其次我们找到“管理工具...
  • windows内存泄露检测

    2021-02-04 15:10:46
    windows内存泄露检测一、VLD简介二、测试代码三、重要说明 一、VLD简介 VLD(Visual Leak Detector)是一款用于 Visual C++ 的免费内存泄露检测工具。相比较其它内存泄露检测工具,它在检测到内存泄漏的同时,还具有...
  • Windows查询内存内存条)信息

    千次阅读 2021-07-30 10:05:30
    Windows查询内存内存条)信息 查询步骤 1.WIN+R打开cmd 2.输入wmic回车 3.输入memorychip回车即可查询到内存详细信息
  • Windows11 出现桌面管理器dwm.exe占用内存过高的解决方法 自从我更新完Windows11之后,这种现象就一直缠着我,每次都要重启才能得到解决,之前看过网上很多的解决方案,比如 1.在电源管理中关闭快速启动功能。 2....
  • 资源管理器有时候会内存暴涨或者进入无响应状态,这时候在任务管理器中关闭它或者直接关掉窗口,都会导致桌面上的开始菜单直接消失。 但其实这时候电脑是能运行其他程序的,所以可以ctrl+alt+delete,打开任务管理器...
  • Windows内存诊断工具(1)回忆起旧时对电脑升级时安装的2MB的桌面类型内存,当时那个开心愉快的样子!而那时候的服务器内存如果是64MB的已经是相当相当(原文sooooo much memory)大的了。可以想象那时候每兆字节的价值...
  • Windows服务器查看内存型号 内容精选换一换以Windows 2008 R2 64bit为例,介绍查询Windows弹性云服务器磁盘分区与磁盘设备对应关系的方法。登录Windows弹性云服务器。单击桌面左下角的“开始”菜单。选择“控制面板 ...
  • 304-Windows内存管理

    2021-05-02 12:54:20
    Windows内存管理 Windows虚拟内存管理程序控制如何分配内存以及如何执行分页。内存管理程序设计成可以在各种平台上执行,并且使用的页尺寸可以从4KB一直到6KB。Intel和AMD64平台每页有4096个字节,而Intel Itanium...
  • 内存主要是用来存放各种现场的输入输出数据、中间计算结果,以及与外部存储器交换信息和作堆栈用。电脑对它的要求是"韩信点兵--多多益善"。假若你的电脑内存不足而又不想增加内存,有没有充分利用现有内存的办法呢?...
  • windows内存诊断工具有什么作用

    千次阅读 2021-05-26 05:23:15
    如果最近你的电脑用起来不太稳定,经常无故蓝屏重启等等,又不知道是不是内存条引起的,这里告诉大家一个方法, 可以快速做出判断。1、它就是系统自带的内存诊断功能,我们先打开控制面板,如下图。2、打...
  • windows内存诊断工具有什么用导读:内存可以说是电脑的重灾区,很多电脑问题都跟内存有关。内存稍微有点问题都有可能导致系统运行不稳定,最常见的表现就是蓝屏,自动重启,甚至开不起机。如果是开不起机的话反倒好...
  • Linux与WindowsNT在内存管理上的差别(转)[@more@] 在内存管理上,Linux 和Windows NT在面对相同的进程地址空间大小时,对内存布局的使用方式不同。Windows NT实际只为进程准备了2GB弱的可用虚拟地址空间,而Linux中...
  • windows服务器内存清理

    2021-08-11 10:58:04
    windows服务器内存清理 内容精选换一换本节操作指导您完成Windows操作系统云服务器磁盘空间清理。弹性云服务器匀出一部分磁盘空间来充当内存使用,当内存耗尽时,云服务器可以使用虚拟内存来缓解内存的紧张。但当...
  • 内存检测工具可以检测出内存的稳定度,还...那么Windows10自带内存检测工具怎么用?下面一起看看使用方法。1、在Windows10系统桌面,依次点击“开始/Windows系统/控制面板”菜单项;2、在打开的控制面板窗口中,点...
  • 本文主要介绍STL的内存管理策略。早期的STL内存管理第一次接触STL源码是看侯捷先生的《STL源码剖析》,此书通俗易懂,剖析透彻,是极佳的STL分析教程。不过由于是在2002年出版的,所以内容有些陈旧,不过仍然具有...
  • Win10内存管理探索

    2021-03-29 23:33:41
    然后就开启了我的内存管理探索之旅~ 1. 任务管理器—内存解析 查看内存状况的第一反应是,任务管理器~ 我们发现一个奇怪的事情,PyCharm 848MB占16.3%?算下来,我们的内存只有5个G左右?不是8个G嘛? **PS:**...
  • windows 内存过高解决办法

    千次阅读 2021-03-23 14:27:59
    开始菜单右键选择“windows powershell(管理员)”输入以下命令 关闭内存压缩:Disable-MMAgent -mc 原因二 计算机自动分配的虚拟内存过高,导致开机内存占用80 解决办法 控制面板——>系统和安全——>系统...
  • 我们在使用win7操作性系统进行日常工作学习的时候,对于一些...详细步骤就来看下小编是怎么做的吧~windows7内存不足怎么办1,右击计算机,选择属性选项。计算机在win7可能桌面上没有,单击开始菜单既可以看见,一...
  • windows照片查看器无法显示此图片,因为计算机上的可用内存可能不足解决方法 3、打开颜色管理窗口,点击“高级”。 windows照片查看器无法显示此图片,因为计算机上的可用内存可能不足解决方法 4、点击“校准...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 420,972
精华内容 168,388
关键字:

windows内存管理方式