【问题标题】:Virtual address space in the context of programming编程上下文中的虚拟地址空间
【发布时间】:2012-03-19 16:45:16
【问题描述】:

我对虚拟地址空间的含义感到困惑。在 32 位机器中,一个进程可以寻址 2^32 个内存位置。这是否意味着每个进程的虚拟地址空间是 2^32 (4GB) ?

下面是一个进程的虚拟地址空间的快照。这可以增长到4GB吗?这样的系统中的进程数有限制吗?

【问题讨论】:

    标签: c memory-management


    【解决方案1】:

    这可以增长到 4GB 吗?

    地址空间的大小受唯一指针值的数量限制。对于 32 位处理器,一个 32 位值可以表示 2 ^ 32 个不同的值。如果您允许每个这样的值寻址不同的内存字节,您将获得 2 ^ 32 字节,即 4 GB。

    所以,是的,一个进程的虚拟地址空间理论上可以增长到 4 GB。然而实际上,这也可能取决于系统和处理器。可以看出:

    但是,奔腾类处理器无法达到这个理论上的最大值。一个原因是段值的低位编码有关选择器类型的信息。因此,在 65536 个可能的选择器值中,只有 8191 个可用于访问用户模式数据。这会将您降至 32TB。

    请注意,有两种方法可以从系统分配内存,当然,您可以使用 C 的 malloc(您的问题标记为 隐式为您的进程分配内存,但显式映射文件字节。

    这样的系统中的进程数有限制吗?

    一个进程包含一个或多个线程,这些线程实际执行进程中的代码(从技术上讲,进程不运行,线程运行)并用内核线程对象表示。

    根据here进行的一些测试,具有2GB默认地址空间的32位Windows XP系统可以创建大约2025个线程:

    但是,在分配了 4GB 地址空间的 64 位 Windows XP 上运行的 32 位测试限制 创建了接近 3204 个线程:

    但是,确切的线程和进程限制是非常可变的,这取决于很多因素。线程指定其堆栈大小的方式、进程指定其最小工作集的方式、可用物理内存量和系统提交限制的方式。在任何情况下,您通常不必在现代系统上担心这一点,因为如果您的应用程序真的超过线程限制,您应该重新考虑您的设计,因为几乎总是有替代方法来完成相同的目标,数量合理。

    【讨论】:

    • Vista 64 上的 32 位应用程序 - 我目前的记录,一个应用程序中有 4000 个线程,(总共超过 5000 个),没问题,(最大堆栈大小设置为 128K)。
    • 只是为了好玩,我将堆栈设置为 65536,可以在一个应用程序上创建 5000 个线程。尝试 6000 导致“线程创建错误”异常框 :(.
    • 有人计算非 Windows NT 机器上的最大线程数吗?我在任何地方都找不到这方面的任何信息。
    【解决方案2】:

    是的,在 32 位系统上每个进程的虚拟地址空间为 4GB(232 字节)。实际上,实际使用的少量虚拟内存对应于处理器缓存、物理内存或磁盘(或计算机决定放置内容的其他位置)中的位置。

    理论上(这种行为在常见操作系统中非常普遍),如果操作系统决定将物理内存中无法容纳的所有内容放到磁盘上,进程实际上可以使用其所有虚拟内存,但这会使该程序非常慢,因为每次它试图访问一些未缓存的内存位置时,它都必须从磁盘中获取它。

    您问您提供的图片是否可以增长到 4GB。其实你给的图片已经占满了4GB。这是一种将进程的 4GB 虚拟内存划分为不同部分的方法。此外,如果您正在考虑堆和堆栈“增长”,它们并没有真正增长。他们在该分区布局中为他们分配了一定数量的内存,并且他们只是根据需要使用该内存(堆栈移动指针,堆维护已使用和未使用内存的数据结构等)。

    【讨论】:

    • “如果操作系统决定将它无法放入物理内存的所有内容都放到磁盘上”...请原谅我,但这并不是所有现代桌面/服务器操作系统所做的(Windows ,OS X,Linux,BSD)? (也就是说,除非您专门禁用该功能。)
    • @DietrichEpp 是的,但强调一切,我不想说什么是确定的,什么时候计算机真的可以做它想做的事。跨度>
    • 除了把它放在磁盘上之外,它还能对那些不适合内存的数据做什么? (假设它还没有在磁盘上。)
    • @DietrichEpp 它可能会停止尝试并给你一个内存分配错误。
    • Linux 不这样做。如果你要求的内存比你拥有的多,它会杀死一个进程来为你获取它,但它不会返回错误。
    【解决方案3】:

    你读过维基百科的virtual memoryprocessaddress space 页面吗?

    你读过什么关于advanced unix programming的书?或advanced linux programming

    通常,地址空间是一组有效的段(图中不是蓝色的)。

    另请参阅 mmap(2)execve(2) 页面。

    尝试(在 Linux 系统上)

    cat /proc/self/maps
    

    cat /proc/$$/maps
    

    多了解一点。

    另见this questionthis。阅读Operating Systems: Three Easy Pieces

    当然,内核可以设置一些限制(另见setrlimit(2) syscall)。它们是资源限制(交换空间、RAM 等)。

    【讨论】:

      【解决方案4】:

      回答被忽略的部分...

      可以有多少进程是有限制的。内核保留在其虚拟地址空间部分(这是共享的,否则您将无法在每个进程中访问内核)中的所有每个进程的数据结构都会占用一些空间。因此,例如,如果有 1GB 可用于此数据并且内核中每个进程只需要一个 4KB 页面,那么您最多可以得到大约 250,000 个进程。在实践中,这个数字通常要小得多,因为事情更复杂,并且为每个进程的各种事情保留了物理内存。例如,请参阅Mark Russinovich's article on process and thread limits in Windows 了解更多详情。

      【讨论】:

      • 这是共享的,否则你将无法在每个进程中访问内核:我不明白你的意思它是共享的乙>。谁共享什么?
      • 例如,如果 there 的 1GB 可用于 this 数据:在哪里?哪些数据?
      • @ptr_user7813604 内核的虚拟地址空间部分是共享的。它存在于每个进程的虚拟地址空间中。此部分的大小有限(4 GB 中的 1 或 2 GB)。因此,例如,如果您使用 4KB 内存页来描述每个进程状态,而您只有 1GB 的内核部分的 VAS,则最多 250K 进程。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-18
      • 2012-03-06
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多