精华内容
下载资源
问答
  • 虚拟地址空间

    万次阅读 多人点赞 2019-03-13 03:32:18
    对于每一个进程都会对应一个虚拟地址空间,对于32位的操作系统(其指令的位数最大为32位,因此地址码最多32位),虚拟地址空间的大小为B即0~4GB的虚拟地址空间,其中内核空间为1GB,如下所示: 每一个进程的进程...

            对于每一个进程都会对应一个虚拟地址空间,对于32位的操作系统(其指令的位数最大为32位,因此地址码最多32位),虚拟地址空间的大小为2^{32}B即0~4GB的虚拟地址空间,其中内核空间为1GB,如下所示:

             每一个进程的进程控制块PCB都位于内核区,在每一个进程的PCB中有一个文件描述符表(是一个数组),用于标记该进程所打开的所有文件。从文件描述符表可以看出每一个进程最多能打开1024个文件,其中有三个文件默认是一直处于打开状态的(即进程创建完成时就处于打开状态),分别是:标准输入 STDIN_FILENO,其文件描述符为0;标准输出 STDOUT_FILENO,其文件描述符为1;错误输出 STDERR_FILENO,其文件描述符为2,其中文件描述符0和1可以省略不写。供我们用户打开的文件,只能够占据从3开始的位置(即其文件描述符为3以后的数字,3~1023)。每打开一个文件就会占用一个文件描述符,且使用的是空闲的最小的一个文件描述符。

            Linux下可执行文件的格式为ELF:[root@localhost Calc]# file zsx
                                                                         zsx: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x14ef2d34126e7c54141b73c31968bd825ca522ba, not stripped           //可以看出zsx为64位(即机器指令位数为64位,OS位数)的可执行文件,其格式为ELF。

            对于每一个程序在执行时(如上图中的a.out),此时会产生一个相应的进程,系统都会自动为其分配一个0~4G的虚拟地址空间,其中1G的内核空间用于:进程管理、内存管理、设备管理和虚拟文件系统等。下面详细介绍0~3G的用户空间。

             强调一点:以下说明的各段都是与编程相关的,不包括虚拟地址空间的全部。

            0~3G的用户空间。从小到大(从下往上)依次为:保留区(受保护的地址)、代码段、数据段(.data段)、.bss段、堆空间、内存映射段、栈空间、命令行参数和环境变量。下面依次对每一个段做简单的介绍:

    1.保留区(受保护的地址)

            保留区即为受保护的地址,大小为0~4K,位于虚拟地址空间的最低部分,未赋予物理地址(不会与内存地址相对应,因此其不会放任何内容)。任何对它的引用都是非法的,用于捕捉使用空指针和小整型值指针引用内存的异常情况。大多数操作系统中,极小的地址通常都是不允许访问的,如NULL。C语言将无效指针赋值为0也是出于这种考虑,因为0地址上正常情况下不会存放有效的可访问数据。将指针赋值为0,意味着该指针将永远不会被使用,从而不会出现野指针情况。#define NULL 0 与 #define NULL (void*)0   在C语言中是等效的,而在C++中,只能用#define NULL 0,后面 #define NULL (void*)0的使用会出错。

    2.代码段

            代码段也称正文段或文本段,通常用于存放程序执行代码(即CPU执行的机器指令)。一般C语言执行语句都编译成机器代码保存在代码段。通常代码段是可共享的,因此频繁执行的程序只需要在内存中拥有一份拷贝即可。代码段通常属于只读,以防止其他程序意外地修改其指令(对该段的写操作将导致段错误)。某些架构也允许代码段为可写,即允许修改程序。  

    3.数据段(.data段)

            数据段通常用于存放程序中已初始化的全局变量和静态局部变量。数据段属于静态内存分配(静态存储区),可读可写。由于全局变量未初始化时,其默认值为0,因此值为0的全局变量位于.bbs段(不位于数据段)。对于未初始化的局部变量,其值是不可预测的。注意:在代码段和数据段之间还包括其它段:只读数据段和符号段等。

    4..bbs段

            该段用于存放未初始化的全局变量和静态局部变量,包括值为0的全局变量。 数据段和.bbs段又称为全局数据区,前者初始化,后者未初始化。

            ELF段包括:代码段、其它段(只读数据段和符号段等)、.data段(数据段)和.bbs段,都属于可执行程序部分。

    5.堆空间

            new( )和malloc( )函数分配的空间就属于对空间,用于内存空间的分配,其从下往上。  堆用于存放进程运行时动态分配的内存段,可动态扩张或缩减。堆中内容是匿名的,不能按名字直接访问,只能通过指针间接访问。当进程调用malloc(C) 和new (C++)等函数分配内存时,新分配的内存动态添加到堆上(扩张);当调用free(C)/delete(C++)等函数释放内存时,被释放的内存从堆中剔除(缩减) 。

    6.内存映射段(共享库)

            此处,内核将硬盘文件的内容直接映射到内存, 任何应用程序都可通过Linux的mmap()系统调用请求这种映射。内存映射是一种方便高效的文件I/O方式, 因而被用于装载动态共享库。如C标准库函数(fread、fwrite、fopen等)和Linux系统I/O函数,它们都是动态库函数,其中C标准库函数都被封装在了/lib/libc.so库文件中,都是二进制文件。这些动态库函数都是与位置无关的代码,即每次被加载进入内存映射区时的位置都是不一样的,因此使用的是其本身的逻辑地址,经过变换成线性地址(虚拟地址),然后再映射到内存。而静态库不一样,由于静态库被链接到可执行文件中,因此其位于代码段,每次在地址空间中的位置都是固定的。

    7.栈空间

            用于存放局部变量(非静态局部变量,C语言称为自动变量),分配存储空间时从上往下。栈和堆都是后进先出的数据结构。

    8.命令行参数

            该段用于存放命令行参数的内容:argc和argv。

    9.环境变量

            用于存放当前的环境变量,在Linux中用env命令可以查看其值。

    10.虚拟地址空间的作用(好处)

            1.方面编译器和操作系统安排程序的地址;2.方便实现各个进程空间之间的隔离,互不干扰,因为每个进程都对应自己的虚拟地址空间;3.实现虚拟存储,从逻辑上扩大了内存。

    补充内容:

    代码段(.text段)与只读数据段和符号段(.rodata段),都属于只能读的部分,在链接的时候这两部分会链接成为一个整体;而.data段和.bbs段属于可读可写RW的部分。这四个部分都是以页(每页4KB)的形式存放在内存中。进程控制块PCB(又叫进程描述符)放于内核空间

    多个进程在并发执行时,这些进程的用户空间都是彼此独立的,因此各个进程的用户空间在映射为内存空间使都是独立的,互不干扰,这是MMU地址变换必须要能够保证的。例如,各个进程的.text段、只读数据段和符号段、.data段和.bbs段等在用户空间中使用到的其它数据信息,都会与页为基本单位放在内存中,各个进程的映射是独立的。而对于内核空间,由于只有一个操作系统,内核空间主要是 机器指令、操作系统内核的各个模块等,它们是公用的,因此每个进程的映射方式一样。强调一点:每个进程用到或即将用到的数据才会调入内存,其余都在磁盘上。但是各个进程内核空间的进程控制块(进程描述符)映射的地点是不一样的,也是相互独立的。共用的模块才是一样的。 这些都是MMU的实现机制所决定的。如果感兴趣,可以看看MMU的实现机制。

    展开全文
  • 虚拟地址空间映射到物理地址空间

    千次阅读 2018-09-07 09:06:45
    虚拟地址空间映射到物理地址空间参考如下  当处理器读或写入内存位置时,它会使用虚拟地址。作为读或写操作的一部分,处理器将虚拟地址转换为物理地址。通过虚拟地址访问内存有以下优势:  程序可以使用一系列...

    虚拟地址空间映射到物理地址空间参考如下

      当处理器读或写入内存位置时,它会使用虚拟地址。作为读或写操作的一部分,处理器将虚拟地址转换为物理地址。通过虚拟地址访问内存有以下优势:

      程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区。

      程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。

      不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程或操作系统使用的物理内存。

      进程可用的虚拟地址范围称为该进程的“虚拟地址空间”。每个用户模式进程都有其各自的专用虚拟地址空间。 对于 32 位进程,虚拟地址空间通常为 2 GB,范围从 0x00000000 至 0x7FFFFFFF。对于 64 位进程,虚拟地址空间为 8 TB,范围从 0x000'00000000 至 0x7FF'FFFFFFFF。一系列虚拟地址有时称为一系列“虚拟内存”。

      此图说明了虚拟地址空间的一些重要功能。

                                                                      èæå°å空é´æ å°å°ç©çå°å空é´

     

    该图显示了两个 64 位进程的虚拟地址空间:Notepad.exe 和 MyApp.exe。每个进程都有其各自的虚拟地址空间,范围从 0x000'0000000 至 0x7FF'FFFFFFFF。每个阴影框都表示虚拟内存或物理内存的一个页面(大小为 4 KB)。注意,Notepad 进程使用从 0x7F7'93950000 开始的虚拟地址的三个相邻页面。但虚拟地址的这三个相邻页面会映射到物理内存中的非相邻页面。而且还注意,两个进程都使用从 0x7F7'93950000 开始的虚拟内存页面,但这些虚拟页面都映射到物理内存的不同页面。

      用户空间和系统空间

      诸如 Notepad.exe 和 MyApp.exe 的进程在用户模式下运行。核心操作系统组件和多个驱动程序在更有特权的内核模式下运行。有关处理器模式的详细信息,请参阅用户模式和内核模式。每个用户模式进程都有其各自的专用虚拟地址空间,但在内核模式下运行的所有代码都共享称为“系统空间”的单个虚拟地址空间。当前用户模式进程的虚拟地址空间称为“用户空间”。

      在 32 位 Windows 中,可用的虚拟地址空间共计为 2^32 字节(4 GB)。通常较下的 2 GB 用于用户空间,较上的 2 GB 用于系统空间。

                                                            èæå°å空é´æ å°å°ç©çå°å空é´

     

    在 32 位 Windows 中,你可以指定(在启动时)超过 2 GB 用于用户空间。结果是系统空间可用的虚拟地址更少。可以将用户空间的大小增至 3 GB,在这种情形下系统空间仅有 1 GB。若要增大用户空间的大小,请使用 BCDEdit /set increaseuserva。

      在 64 位 Windows 中,虚拟地址空间的理论大小为 2^64 字节(16 百亿亿字节),但实际上仅使用 16 百亿亿字节范围的一小部分。范围从 0x000'00000000 至 0x7FF'FFFFFFFF 的 8 TB 用于用户空间,范围从 0xFFFF0800'00000000 至 0xFFFFFFFF'FFFFFFFF 的 248 TB 的部分用于系统空间。

                                                                                              èæå°å空é´æ å°å°ç©çå°å空é´

    用户模式下运行的代码可以访问用户空间,但不能访问系统空间。此限制可防止用户模式代码读或更改受保护的操作系统数据结构。内核模式下运行的代码既可以访问用户空间,也可以访问系统空间。即,在内核模式下运行的代码可以访问系统空间和当前用户模式进程的虚拟地址空间。

      在内核模式下运行的驱动程序必须在直接从用户空间地址中读取或写入这些地址时非常小心。此方案说明了原因。

      用户模式程序发起从设备读取某些数据的请求。程序提供缓冲区的起始地址以接收数据。

      在内核模式下运行的设备驱动程序例程启动读取操作并将控制权返回到其调用程序。

      然后,设备中断了当前运行的任何线程以显示读取操作完成。 中断由在此任意线程上运行的内核模式驱动程序例程进行处理,该例程属于任意进程。

      此时,驱动程序不得将数据写入用户模式程序在步骤 1 中提供的开始地址。此地址位于发起请求的进程的虚拟地址空间,该进程可能很大程度上不同于当前进程。

      虚拟地址(Virtual Address Space)

      Win32通过一个两层的表结构来实现地址映射,因为每个进程都拥有私有的4G的虚拟内存空间,相应的,每个进程都有自己的层次表结构来实现其地址映射。

      第一层称为页目录,实际就是一个内存页,Win32的内存页有4KB大小,这个内存页以4个字节分为1024项,每一项称为“页目录项”(PDE);

      第二层称为页表,这一层共有1024个页表,页表结构与页目录相似,每个页表也都是一个内存页,这个内存页以4KB的大小被分为1024项,页表的每一项被称为页表项(PTE),易知共有1024×1024个页表项。每一个页表项对应一个物理内存中的某一个“内存页”,即共有1024×1024个物理内存页,每个物理内存页为4KB,这样就可以索引到4G大小的虚拟物理内存。

      如下图所示(注下图中的页目录项的大小应该是4个字节,而不是4kB):

                                      èæå°å空é´æ å°å°ç©çå°å空é´

    Win32提供了4GB大小的虚拟地址空间。因此每个虚拟地址都是一个32位的整数值,也就是我们平时所说的指针,即指针的大小为4B。它由三部分组成,如下图: 

                                      

    这三个部分的第一部分,即前10位为页目录下标,用来寻址页目录项,页目录项刚好1024个。找到页目录项后,找对页目录项对应的的页表。第二部分则是用来在页表内寻址,用来找到页表项,共有1024个页表项,通过页表项找到物理内存页。第三部分用来在物理内存页中找到对应的字节,一个页的大小是4KB,12位刚好可以满足寻址要求。

      具体的例子:

      假设一个线程正在访问一个指针(Win32的指针指的就是虚拟地址)指向的数据,此指针指为0x2A8E317F,下图表示了这一个过程:

                                                 

     

    0x2A8E317F的二进制写法为0010101010_0011100011_000101111111,为了方便我们把它分为三个部分。

      首先按照0010101010寻址,找到页目录项。因为一个页目录项为4KB,那么先将0010101010左移两位,001010101000(0x2A8),用此下标找到页目录项,然后根据此页目录项定位到下一层的某个页表。

      然后按照0011100011寻址,在上一步找到页表中寻找页表项。寻址方法与上述方法类似。找到页表项后,就可以找到对应的物理内存页。

      最后按照000101111111寻址,寻找页内偏移。

      上面的假设的是此数据已在物理内存中,其实判断访问的数据是否在内存中也是在地址映射过程中完成的。Win32系统总是假设数据已在物理内存中,并进行地址映射。页表项中有一位标志位,用来标识包含此数据的页是否在物理内存中,如果在的话,就直接做地址映射,否则,抛出缺页中断,此时页表项也可标识包含此数据的页是否在调页文件中(外存),如果不在则访问违例,程序将会退出,如果在,页表项会查出此数据页在哪个调页文件中,然后将此数据页调入物理内存,再继续进行地址映射。为了实现每个进程拥有私有4G的虚拟地址空间,也就是说每个进程都拥有自己的页目录和页表结构,对不同进程而言,即使是相同的指针(虚拟地址)被不同的进程映射到的物理地址也是不同的,这也意味着在进程之间传递指针是没有意义的。

      看过“虚拟地址空间映射到物理地址空间 ”的人还看了:

    1.物理地址与虚拟地址映射

    2.linux虚拟地址怎么映射物理地址

    3.物理地址和虚拟地址

    4.物理地址与虚拟地址怎么转换

    5.Linux关于虚拟内存

     

    展开全文
  • 对虚拟地址空间对应实际物理地址的理解

    千次阅读 多人点赞 2018-12-18 23:22:16
    在 早期的计算机中,要运行一个程序,会把这些程序全都装入内存,程序都是直接运行在内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序用到的内存总量...

     

    在进入正题前先来谈谈操作系统内存管理机制的发展历程,了解这些有利于我们更好的理解目前操作系统的内存管理机制。

    一 早期的内存分配机制

    在 早期的计算机中,要运行一个程序,会把这些程序全都装入内存,程序都是直接运行在内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序用到的内存总量要小于计算机实际物理内存的大小。那当程序同时运行多个程序时,操作系统是如何为这些程序分配内存 的呢?下面通过实例来说明当时的内存分配方法:

    某台计算机总的内存大小是 128M ,现在同时运行两个程序 A 和 B , A 需占用内存 10M , B 需占用内存 110 。计算机在给程序分配内存时会采取这样的方法:先将内存中的前 10M 分配给程序 A ,接着再从内存中剩余的 118M 中划分出 110M 分配给程序 B 。这种分配方法可以保证程序 A 和程序 B 都能运行,但是这种简单的内存分配策略问题很多。

     

     

    图一 早期的内存分配方法

    问题 1 :进程地址空间不隔离。由于程序都是直接访问物理内存,所以恶意程序可以随意修改别的进程的内存数据,以达到破坏的目的。有些非恶意的,但是有 bug 的程序也可能不小心修改了其它程序的内存数据,就会导致其它程序的运行出现异常。这种情况对用户来说是无法容忍的,因为用户希望使用计算机的时候,其中一个任务失败了,至少不能影响其它的任务。

    问题 2 :内存使用效率低。在 A 和 B 都运行的情况下,如果用户又运行了程序 C ,而程序 C 需要 20M 大小的内存才能运行,而此时系统只剩下 8M 的空间可供使用,所以此时系统必须在已运行的程序中选择一个将该程序的数据暂时拷贝到硬盘上,释放出部分空间来供程序 C 使用,然后再将程序 C 的数据全部装入内存中运行。可以想象得到,在这个过程中,有大量的数据在装入装出,导致效率十分低下。

    问题 3 :程序运行的地址不确定。当内存中的剩余空间可以满足程序 C 的要求后,操作系统会在剩余空间中随机分配一段连续的 20M 大小的空间给程序 C 使用,因为是随机分配的,所以程序运行的地址是不确定的。

    二 分段

    为 了解决上述问题,人们想到了一种变通的方法,就是增加一个中间层,利用一种间接的地址访问方法访问物理内存。按照这种方法,程序中访问的内存地址不再是实际的物理内存地址,而是一个虚拟地址,然后由操作系统将这个虚拟地址映射到适当的物理内存地址上。这样,只要操作系统处理好虚拟地址到物理内存地址的映 射,就可以保证不同的程序最终访问的内存地址位于不同的区域,彼此没有重叠,就可以达到内存地址空间隔离的效果。

    当创建一个进程时,操作系统会为该进程分配一个 4GB 大小的虚拟进程地址空间。之所以是 4GB ,是因为在 32 位的操作系统中,一个指针长度是 4 字节,而 4 字节指针的寻址能力是从 0x00000000~0xFFFFFFFF ,最大值 0xFFFFFFFF 表示的即为 4GB 大小的容量。与虚拟地址空间相对的,还有一个物理地址空间,这个地址空间对应的是真实的物理内存。如果你的计算机上安装了 512M 大小的内存,那么这个物理地址空间表示的范围是 0x00000000~0x1FFFFFFF 。当操作系统做虚拟地址到物理地址映射时,只能映射到这一范围,操作系统也只会映射到这一范围。当进程创建时,每个进程都会有一个自己的 4GB 虚拟地址空间。要注意的是这个 4GB 的地址空间是“虚拟”的,并不是真实存在的,而且每个进程只能访问自己虚拟地址空间中的数据,无法访问别的进程中的数据,通过这种方法实现了进程间的地址隔离。那是不是这 4GB 的虚拟地址空间应用程序可以随意使用呢?很遗憾,在 Windows 系统下,这个虚拟地址空间被分成了 4 部分: NULL 指针区、用户区、 64KB 禁入区、内核区。应用程序能使用的只是用户区而已,大约 2GB 左右 ( 最大可以调整到 3GB) 。内核区为 2GB ,内核区保存的是系统线程调度、内存管理、设备驱动等数据,这部分数据供所有的进程共享,但应用程序是不能直接访问的。

          人们之所以要创建一个虚拟地址空间,目的是为了解决进程地址空间隔离的问题。但程序要想执行,必须运行在真实的内存上,所以,必须在虚拟地址与物理地址间建立一种映射关系。这样,通过映射机制,当程序访问虚拟地址空间上的某个地址值时,就相当于访问了物理地址空间中的另一个值。人们想到了一种分段 (Sagmentation) 的方法,它的思想是在虚拟地址空间和物理地址空间之间做一一映射。比如说虚拟地址空间中某个10M 大小的空间映射到物理地址空间中某个10M 大小的空间,可以多对一,就是说可虚拟地址的多个10M大小的空间可以映射到相同的物理地址空间的某个10M。这种思想理解起来并不难,操作系统保证不同进程的地址空间被映射到物理地址空间中不同的区域上,这样每个进程最终访问到的

    物理地址空间都是彼此分开的。通过这种方式,就实现了进程间的地址隔离。还是以实例说明,假设有两个进程 A 和 B ,进程 A 所需内存大小为 10M ,其虚拟地址空间分布在 0x00000000 到 0x00A00000 ,进程 B 所需内存为 100M ,其虚拟地址空间分布为 0x00000000 到 0x06400000 。那么按照分段的映射方法,进程 A 在物理内存上映射区域为 0x00100000 到 0x00B00000 ,,进程 B 在物理内存上映射区域为 0x00C00000 到 0x07000000 。于是进程 A 和进程 B 分别被映射到了不同的内存区间,彼此互不重叠,实现了地址隔离。从应用程序的角度看来,进程 A 的地址空间就是分布在 0x00000000 到 0x00A00000 ,在做开发时,开发人员只需访问这段区间上的地址即可。应用程序并不关心进程 A 究竟被映射到物理内存的那块区域上了,所以程序的运行地址也就是相当于说是确定的了。 图二显示的是分段方式

    的内存映射方法。

     

     

     

     

    图二 分段方式的内存映射方法

          这 种分段的映射方法虽然解决了上述中的问题一和问题三,但并没能解决问题二,即内存的使用效率问题。在分段的映射方法中,每次换入换出内存的都是整个程序,这样会造成大量的磁盘访问操作,导致效率低下。所以这种映射方法还是稍显粗糙,粒度比较大。实际上,程序的运行有局部性特点,在某个时间段内,程序只是访 问程序的一小部分数据,也就是说,程序的大部分数据在一个时间段内都不会被用到。基于这种情况,人们想到了粒度更小的内存分割和映射方法,这种方法就是分页(Paging) 。  

    三 分页

    分页的基本方法是,将地址空间分成许多的页。每页的大小由 CPU 决定,然后由操作系统选择页的大小。目前 Inter 系列的 CPU 支持 4KB 或 4MB 的页大小,而 PC 上目前都选择使用 4KB 。按这种选择, 4GB 虚拟地址空间共可以分成 1048576 个页, 512M 的物理内存可以分为 131072 个页。显然虚拟空间的页数要比物理空间的页数多得多。

    在分段的方法中,每次程序运行时总是把程序全部装入内存,而分页的方法则有所不同。分页的思想是程序运行时用到哪页就为哪页分配内存,没用到的页暂时保留在硬盘上。当用到这些页时再在物理地址空间中为这些页分配内存,然后建立虚拟地址空间中的页和刚分配的物理内存页间的映射。

    下面通过介绍一个可执行文件的装载过程来说明分页机制的实现方法。一个可执行文件 (PE 文件 ) 其实就是一些编译链接好的数据和指令的集合,它也会被分成很多页,在 PE 文件执行的过程中,它往内存中装载的单位就是页。当一个 PE 文件被执行时,操作系统会先为该程序创建一个 4GB 的进程虚拟地址空间。前面介绍过,虚拟地址空间只是一个中间层而已,它的功能是利用一种映射机制将虚拟地址空间映射到物理地址空间,所以,创建 4GB 虚拟地址空间其实并不是要真的创建空间,只是要创建那种映射机制所需要的数据结构而已,这种数据结构就是页目和页表。

    当创建完虚拟地址空间所需要的数据结构后,进程开始读取 PE 文件的第一页。在 PE 文件的第一页包含了 PE 文件头和段表等信息,进程根据文件头和段表等信息,将 PE 文件中所有的段一一映射到虚拟地址空间中相应的页 (PE 文件中的段的长度都是页长的整数倍 ) 。这时 PE 文件的真正指令和数据还没有被装入内存中,操作系统只是根据 PE 文件的头部等信息建立了 PE 文件和进程虚拟地址空间中页的映射关系而已。当 CPU 要访问程序中用到的某个虚拟地址时,当 CPU 发现该地址并没有相相关联的物理地址时, CPU 认为该虚拟地址所在的页面是个空页面, CPU 会认为这是个页错误 (Page Fault) , CPU 也就知道了操作系统还未给该 PE 页面分配内存, CPU 会将控制权交还给操作系统。操作系统于是为该 PE 页面在物理空间中分配一个页面,然后再将这个物理页面与虚拟空间中的虚拟页面映射起来,然后将控制权再还给进程,进程从刚才发生页错误的位置重新开始执行。由于此时已为 PE 文件的那个页面分配了内存,所以就不会发生页错误了。随着程序的执行,页错误会不断地产生,操作系统也会为进程分配相应的物理页面来满足进程执行的需求。

    分页方法的核心思想就是当可执行文件执行到第 x 页时,就为第 x 页分配一个内存页 y ,然后再将这个内存页添加到进程虚拟地址空间的映射表中 , 这个映射表就相当于一个 y=f(x) 函数。应用程序通过这个映射表就可以访问到 x 页关联的 y 页了。

     

    总结:

    32 位的CPU 的寻址空间是4G , 所以虚拟内存的最大值为4G , 而windows 操作系统把这4G 分成2 部分, 即2G 的用户空间和2G 的系统空间, 系统空间是各个进程所共享的, 他存放的是操作系统及一些内核对象等, 而用户空间是分配给各个进程使用的, 用户空间包括用: 程序代码和数据, 堆, 共享库, 栈。

     

    转自:https://blog.csdn.net/do2jiang/article/details/4690967

     

    展开全文
  • PCIe的内存地址空间、I/O地址空间和配置地址空间

    千次阅读 多人点赞 2018-08-12 18:07:14
    PCIe的内存地址空间、I/O地址空间和配置地址空间 pci设备与其它接口的设备(如i2c设备)最大的不同是存在内存地址空间和配置地址空间,本文分析一下它们的用途。 首先区分一下IO空间和内存空间 cpu会访问的设备...

    PCIe的内存地址空间、I/O地址空间和配置地址空间

    pci设备与其它接口的设备(如i2c设备)最大的不同是存在内存地址空间和配置地址空间,本文分析一下它们的用途。

    首先区分一下IO空间和内存空间
    cpu会访问的设备一般有内存和外设寄存器,如下图所示。x86架构采用独立编址将内存操作与外设IO操作分开了才有了内存空间和IO空间的区分。x86平台cpu内部对内存和外设寄存器访问的指令也是不同的。arm等其他平台都采用统一编址,不区分内存和外设的访问,我个人觉得这才是合理的。
    IO空间:访问外部设备寄存器的地址区域,x86平台为64k
    内存空间:访问内存的地址空间,32位平台为4G

    pci设备的内存空间是怎么回事呢
    常见的设备都只提供寄存器供cpu访问,对于低速外设这样的模式是足够的。但是对于需要大量、高速数据交互的外设就需要引入外设内存空间了。在网卡、显卡这样的pci高速外设中不仅有寄存器还有了一块内存

    pci设备的配置空间和IO空间有什么区别呢
    现在我们知道外设内存空间的大概用途了,那配置空间和IO空间不都是外设的寄存器吗࿰

    展开全文
  • Linux用户空间与内核地址空间

    千次阅读 2017-09-02 11:35:54
    Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数据可能不在...
  • 这篇博文可以在你基本了解逻辑地址空间和物理地址空间的概念后,为增强理解可通过我画的示意图来理解,本文会深入一些概念,以达到全面掌握该映射关系的目的。画图不易鸭,点个赞再走呗(✿◡‿◡) 逻辑地址空间及...
  • 程序的地址空间

    千次阅读 2018-08-10 20:18:08
    在32位系统上,线性地址空间可达4G(2^32);这4G一般是按照3:1的比例进行分配,用户进程享有3G的空间,而内核独自享有剩下的1G内存 早期的内存分派方式: 最早的时候,计算机还没有虚拟机制,程序指令所...
  • Windows内存体系(1) -- 虚拟地址空间

    万次阅读 多人点赞 2018-03-19 14:07:17
    在8086或者80186以前,要运行一个程序,操作系统会把这些程序全都装入内存,程序都是直接运行在物理内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序...
  • DLL和进程的地址空间

    万次阅读 2018-11-05 11:38:37
    DLL和进程的地址空间一,MT和MD的区别二,显示链接与隐式链接三,DLL和进程的地址空间 DLL是Windows开发人员经常使用到的一种技术,比如我们经常会把相同功能的代码封装到一个模块中,然后供其他需要使用该模块的...
  • 进程地址空间

    千次阅读 2018-08-02 13:57:01
    进程地址空间: 1.进程 操作系统内核为每个被创建的进程都建立一个PCB(进程控制块或进程描述符)来保存与其相关的信息,PCB存在于进程的高 1 G空间,也就是内核空间中。在具体linux内核实现中,使用一个名为task_...
  • PCI 总线及地址空间

    万次阅读 2016-06-12 12:27:29
    PCI的基本协议这里就不介绍了,因为一般的芯片协议都是集成好...一、地址映射与数据传输 上图中间部分是9054的内部结构图,9054实际上充当了一个“桥”的作用,即所谓的“桥片技术”。9054的作用其实是把LOCAL总线端
  • ARM结构和MIPS结构的地址空间

    千次阅读 2018-08-18 19:02:21
    无论在哪种体系结构中,地址空间的访问都是CPU运行的基本,CPU的每一条指令的地址,都必须在CPU所能访问的地址空间内,当然这个空间指的是虚拟地址空间。每个CPU所能访问多大的虚拟地址这是和CPU的位数有关的,32位...
  • 物理地址空间和虚拟地址空间

    千次阅读 2018-02-18 21:43:18
    因为CPU是32位的,其地址总线是32位的,所以其地址总线可编码的个数是2^32(4G),这2^32个物理地址的集合就是物理地址空间。这与38译码器的道理是一样的,这一点很好理解。 二、虚拟地址(空间)   &...
  • 逻辑地址空间和物理地址空间

    千次阅读 2018-06-15 12:46:24
    地址空间是一个进程可用于寻址内存的一套地址集合。1、程序经过编译后,每个目标模块都是从0号单元开始编址,称为该目标模块的相对地址(或逻辑地址)。2、当链接程序将各个模块链接成一个完整的可执行目标程序时,...
  • 四、地址空间与内存分配

    千次阅读 2018-04-07 16:05:44
    物理地址空间和硬件直接对应,如内存条代表的主存,硬盘代表的磁盘 ,都是物理内存,其管理由硬件完成逻辑地址空间是运行的程序看到的地址空间,是一维的线性的地址空间。逻辑地址空间依赖物理地址空间而存在。2....
  • 内存地址空间

    千次阅读 2018-06-01 17:23:23
    BIOS在内存最高地址处,最低1M空间内又有很多固定的用途,如下图所示: (图片出自:赵炯——Linux内核完全剖析——基于0.12内核,图2-4) 我原来不明白,ROM和RAM是连着的吗?还是把ROM BIOS拷贝到RAM中的指定...
  • Linux虚拟地址空间分布

    千次阅读 2017-06-16 23:35:40
    Linux虚拟地址空间分布
  • 1.4 x86 CPU地址空间分配和寄存器访问

    千次阅读 2017-10-12 11:05:15
    1、基本概念cpu地址空间和pci地址空间是两个常用的比较容易混淆的概念,特别是其中不同系列的cpu的实现还各不相同:x86系列cpu地址空间和pci地址空间是重合的,即为同一空间;而非x86 cpu的cpu地址空间和pci地址空间...
  • Linux进程地址空间和进程的内存分布

    万次阅读 多人点赞 2018-05-15 20:13:18
    原网址为:https://blog.csdn.net/yusiguyuan/article/details/45155035一 进程空间分布概述 对于一个进程,其空间分布如下图所示: 程序段(Text):程序代码在内存中的映射,存放函数体的二进制代码。初始化过的...
  • 根据crash学习ARM64虚拟地址空间布局

    千次阅读 2020-04-08 11:02:49
    每个进程感觉自己都能看到整个虚拟地址空间,大小用TASK_SIZE表示 32位用户空间程序:TASK_SIZE=TASK_SIZE_32=0x100000000=4G (64位内核运行32位应用程序时) 64位用户空间程序:TASK_SIZE=TASK_SIZE_64=1如果地址...
  • Linux虚拟地址空间布局以及进程栈和线程栈总结

    万次阅读 多人点赞 2016-12-21 18:55:46
    一:Linux虚拟地址空间布局 (转自:Linux虚拟地址空间布局)  在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中。这个沙盘就是虚拟地址空间(Virtual Address Space),在32位模式下它是一个4GB的内存...
  • Linux内核地址空间分布

    千次阅读 2017-09-04 11:23:15
    在32位系统里,Linux内核地址空间是指0xC0000000开始到0xFFFFFFFF总量为1G的高端内存地址空间,而用户空间是0x00000000至0xBFFFFFFF的3G虚拟存储空间。操作系统和驱动程序运行在内核空间,应用程序运行在用户空间。 ...
  • 进程虚拟地址空间

    千次阅读 2018-11-06 23:19:45
    进程虚拟地址空间的引入  1.程序与进程的区别 程序: 静态 预先编译好的指令和数据的集合 的一个文件 #菜谱 进程:动态 程序运行的过程 #炒菜的过程  2.虚拟地址空间: 程序运行后拥有自己独立的虚拟空间 大小...
  • CPU地址空间,IO端口和IO内存

    千次阅读 2016-12-11 16:23:59
    1)物理地址:CPU地址总线传来的地址,由硬件 电路控制其具体含义。物理地址中很大一部分是留给内存... 物理地址空间,一部分给物理RAM(内存)用,一部分给总线用,这是由硬件设计来决定的,因此在32 bits地址线的x8
  • 存储容量与地址空间的计算

    千次阅读 2020-09-07 22:38:42
    比如,告诉你某FLASH存储容量8MB,地址空间范围是m~0xFFFFFFFF,让求m 先算出8M对应的16进制数,内存是按照字节编址的,8MB=810241024Byte=2^20*8 =16^5 * 8; 以上写成16进制数为 0x80 0000 求m m=0xFFFFFFFF-0x800000...
  • 进程基本概念、进程地址空间

    千次阅读 2018-03-31 17:54:14
    强调内容今天来谈一谈进程的一些基本概念,认识一些进程状态,重新认识一下程序地址空间(进程地址空间),进程调度算法,环境变量等属性。 一、进程 1.什么是进程? 程序的一个执行实例,正在执行的程序,是一个...
  • 地址空间看进程和线程

    千次阅读 2017-10-20 21:53:10
    地址空间看进程和线程
  • ●在一个系统中,进程是和其他进程共享CPU和主存资源。但是共享资源会造成一些不可避免的问题,例如由于存储器不够而 进程无法运行,亦或是存储器被... 当CPU要执行某条指令时,它会生成一个有效物理地址,通过存...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,412,998
精华内容 565,199
关键字:

地址空间