Linux 内存管理

来源:互联网 发布:桌面会议软件 编辑:程序博客网 时间:2024/06/01 22:20

一. 机制

    Linux 程序不允许直接访问物理内存。而且,如果机器配置正确且有足够的交换空间,Linux 允许程序访问比实际物理地址大得多的内存空间。


二. 大内存分配

    应用程序所分配的内存是由 Linux 内核管理的。每次程序请求内存或者尝试读写它已经分配的内存时,便会由 Linux 内核接管并决定如何处理这些请求。

    开始时,内核只是通过使用空闲的物理内存来满足应用程序的内存请求,但是当物理内存耗尽时,它便会开始使用所谓的交换空间(swap space)。在 Linux 系统中,交换空间是一个在安装系统时分配的独立的磁盘区域。内核会在物理内存和交换空间之间移动数据和程序代码,使得每次读写内存时,数据看起来总像是已存在于物理内存中,而不管在你访问它们之前,它们究竟是在哪里。getconf PAGESIZE

    最终,当应用程序耗尽所有的物理内存和交换空间,或者当最大栈长度被超过时,内核将拒绝此后的内存请求,并可能提前终止程序的运行。

    那么,这种明显的没有限制的内存供应和在内存耗尽前系统提前终止进程的做法是否意味着,对 malloc() 函数的返回值进行检查没有意义呢?显然不是。在 C 语言中,一个最常见的问题是试图在一个已分配的内存块之后写数据。在这种情况下,程序可能不会立即终止,但是可能已经覆盖了 malloc() 库例程内部使用的一些数据,导致后续的 malloc() 调用失败。此时不是因为内存不够,而是内存的结构已经被破坏。


三. 空指针

    对于空指针的写操作,一律不容忍。但是对于空指针的读操作,情况则不同。Linux 在 GNU C 库函数中中容忍了空指针读操作,但如果不使用 GNU C 函数库,则从零地址处读取数据也不允许。


四. realloc()

    该函数用于改变先前已经分配的内存块长度。为了完成这一任务,realloc() 函数可能不得不移动数据,因此,必须使用新指针而不是之前的指针去访问内存。

    另一个需要注意的问题是,如果 realloc() 无法调整内存大小,将返回空指针。因此,如果代码类似下面这样:

    pointer = malloc(BLOCK_SIZE);

    ......

    pointer = realloc(pointer, BLOCK_SIZE * 10);

    如果 realloc() 调用失败,它将返回空指针,pointer 将为 NULL,而先前用 malloc() 分配的内存将无法再通过 pointer 进行访问。因此,在释放老内存块之前,最好的办法是先用 malloc() 请求一块新内存,再通过 memcpy() 调用把数据从老内存块复制到新的内存块。


五. alloca

    程序员这么多年,到今天才听说有个 alloca,在 alloca.h 中声明。该函数用于在调用者的堆栈上分配内存,当调用者返回时自动释放。一听到这个,就能明白为什么不推荐使用,用堆栈的内存根本不用这么费劲。另外,移植性也是一个问题,在没有堆栈的机器上无法实现,因为除了递归调用,堆栈并非必需,因为在编译时可以知道局部变量、参数和返回地址所需空间的固定大小,并可以将其分配于 BSS 段。

原创粉丝点击