memory - 现代系统中的内存管理和段错误(Linux)

标签 memory memory-management linux-kernel operating-system segmentation-fault

在现代操作系统中,内存可用作抽象资源。进程暴露于虚拟地址空间(独立于所有其他进程的地址空间),并且存在用于将任何虚拟地址映射到某个实际物理地址的完整机制。
我的疑问是:

  • 如果每个进程都有自己的地址空间,则应该可以自由访问同一进程中的任何地址。因此,除了权限限制部分(如.data,.bss,.text等)外,应该可以在任何地址自由更改值。但这通常会带来细分错误,为什么呢?
  • 为了获取动态内存,我们需要执行一个malloc。如果整个虚拟空间可供一个进程使用,那么为什么它不能直接访问它呢?
  • 程序的不同运行会导致变量(堆栈和堆)的地址不同。当每次运行的环境相同时,为什么会这样呢?它不会影响可使用的可寻址内存量吗? (这与地址空间随机化有关吗?)
  • 关于内存分配的一些链接(例如在堆中)。

  • 在不同地方获得的数据非常混乱,因为他们谈论的是近代和近代,通常无法区分它们。 Linux说,如果有人能够在牢记现代系统的同时澄清疑问,那将很有帮助。

    谢谢。

    最佳答案

    从技术上讲,操作系统可以在访问时分配任何内存页,但是有重要原因导致它不应该或不能:

    不同的存储区具有不同的用途。

  • 代码。它可以读取和执行,但不应写入。
  • 文字(字符串,const数组)。该内存是只读的,应该是。
  • 堆。可以读取和写入,但不能执行。
  • 线程堆栈。没有理由让两个线程访问彼此的堆栈,因此操作系统也应该禁止这样做。而且,当胎面结束时,胎面堆叠可以被解除分配。
  • 内存映射的文件。对该区域的任何更改都应影响特定的文件。如果该文件已打开以供读取,则同一进程的内存页可能是共享的,因为它是只读的。
  • 内核空间。通常,应用程序不应(或不能)访问该区域-只有内核代码可以。它基本上是内核的临时空间,在进程之间共享。网络缓冲区可能驻留在此处,因此无论数据包何时到达,它始终可用于写入。
  • ...

  • 操作系统可能会假定所有无法识别的内存访问都是尝试分配更多的堆空间,但是:
  • 如果应用程序从用户代码访问内核内存,则必须将其杀死。在32位Windows上,1<<31(高位设置)或3<<30(高位设置)以上的所有内存均为内核内存。您不应该假定用户空间中有任何未分配的内存区域。
  • 如果应用程序考虑使用内存区域但不告诉操作系统,则操作系统可能会为该内存分配其他内容(操作系统:当然,您的文件位于0x12341234;应用程序:但我想在此处存储数据)。您可以通过触摸阵列的末端来告诉操作系统(无论如何这是不可靠的),但是仅调用操作系统函数就更容易了。最好是函数调用是“给我10MB的堆”,而不是“给我10g的开始于0x12345678的堆”
  • 如果应用程序通过使用内存来分配内存,那么它通常根本不会取消分配。这可能会产生问题,因为OS仍然必须保留未使用的页面(但是Java虚拟机也不会取消分配,所以嘿)。

  • 程序的不同运行会导致变量的地址不同

    这称为内存布局随机化,与适当的权限(堆栈空间不可执行)一起使用,使缓冲区溢出攻击更加困难。您仍然可以终止应用程序,但不能执行任意代码。

    内存分配上的某些链接(例如在堆中)。

    您的意思是分配器使用什么算法?最简单的算法是始终分配在最快的可用位置,并从每个存储块链接到下一个存储块,如果是空闲块或已用块,则存储标志。更高级的算法始终以两倍或某个固定大小倍数的幂的大小来分配块,以防止内存碎片(许多小的空闲块)或将这些块链接到不同的结构中,以更快地找到足够大小的空闲块。

    甚至更简单的方法是从不取消分配,而仅指向第一个(也是唯一的)空闲块并保持其大小。如果剩余空间太小,请将其扔掉,然后要求操作系统提供新的空间。

    内存分配器没有什么神奇的。他们所做的就是:
  • 向操作系统询问较大的区域,然后
  • 将其分区为较小的块
  • 不含

  • 浪费太多空间或
  • 花了太长时间。

  • 无论如何,维基百科有关内存分配的文章是http://en.wikipedia.org/wiki/Memory_management

    一种有趣的算法称为"(binary) buddy blocks"。它拥有多个2的幂的池,并将它们递归地分成较小的区域。然后,每个区域要么完全分配,完全自由,要么分为两个都不都是完全自由的区域(预算)。如果已拆分,则一个字节足以容纳此块中最大的空闲块的大小。

    关于memory - 现代系统中的内存管理和段错误(Linux),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13522931/

    相关文章:

    Docker 服务禁用内存交换

    c++ - 堆上的多线程(取消)分配

    onStop(或屏幕外) Activity 的Android内存管理

    c - 为什么要定义一个宏而不是直接使用?(请看我想要什么的描述)

    linux-kernel - 如何将bio分成多个bios?

    c - Linux 内核未将完整结构传递给 sysfs 回调

    python - 分配形状为 OOM 的张量[1,144,144,144,128]

    flash - Adobe AIR 可以使用的最大内存量是多少?

    memory - .txt 文件大小有上限吗?

    c - Malloc 和 free 错误