linux系统编程-内存管理day05

2018-05-29  本文已影响0人  桔子满地

内存锁定

linux实现了请求页面调度(在需要时将页面从硬盘交换进来,当不再需要时再交换出去),这使得系统中进程的虚拟地址空间与实际的物理内存大小没有直接的关系。
交换对进程来说是透明的,应用程序一般都不需要关心内核页面调度的行为。然而在下面两种情况下,应用程序可能希望影响系统的页面调度:


锁定部分地址空间

POSIX1003.1b-1993定义两个接口将一个或多个页面“锁定”在物理内存,来保证它们不会被交换到磁盘。

  1. mlock( ):
    mlock( )锁定给定的一个地址空间:
#include <sys/mman.h>
int mlock(const void *addr, size_t len);

调用mlock( )将锁定addr开始长度为len个字节的虚拟内存。成功时函数返回0,失败返回-1,并适当设置errno。

  1. mlockall( ):
    如果一个进程想在物理内存中锁定它的全部地址空间,可以使用mlockall( ):
#include <sys/mman.h>
int mlockall(int flags);

mlockall( )函数锁定一个进程现有的地址空间在物理内存中的所有页面。
flags参数,是下面两个值的按位或操作,用以控制函数行为:(大部分应用程序会同时设定这两个值)


内存解锁

POSIX标准提供了两个接口用来将页从内存中解锁,允许内核根据需要将页换出至硬盘中。

#include <sys/mman.h>
int munlock(const void *addr, size_t len);
in munlockall(void);

内存锁定并不会重叠,所以不管mlock( )或mlockall( )了几次,仅一个munlock( )或munlockall( )会解除一个页面的锁定。

linux对于一个进程能锁定的页面数进行了限制:拥有CAP_IPC_LOCK权限的进程能锁定任意多的页面。没有这个权限的进程只能锁定RLIMIT_MEMLOCK个字节,默认情况下,该限制是32KB


判断一个页面在不在物理内存中

mincore( )函数,用来确定一个给定范围的内存是在物理内存中还是被交换到了硬盘中:

#include <unistd.h>
#include <sys/mman.h>
int mincore(void *start, size_t length, unsigned char *vec);

函数通过vec来返回向量,这个向量描述start(必须页面对齐)开始长为length(不需要对齐)字节的内存中的页面的情况。


投机性存储分配策略

Linux使用投机性分配策略:当一个进程向内核请求额外的内存-如扩大它的数据段,或者创建一个新的存储器映射-内核作出了分配承诺但实际上并没有分给进程任何的物理存储

这样处理有如下几个优点

  1. 延缓内存分配允许内核将大部分工作推迟到最后一刻(当确实需要进行分配时)
  2. 由于请求是根据需求逐页的分配,只有真正需要物理内存的时候才会消耗物理存储
  3. 分配到的内存可能比实际的物理内存甚至比可用的交换空间多的多,这个特征叫超量使用

超量使用和内存耗尽

超量使用的好处:和在应用请求页面就分配物理存储相比,在使用时刻才分配物理存储的过量使用机制允许系统运行更多,更大的应用程序
但是,如果系统中的进程为满足超量使用而申请的内存大于物理内存和交换空间之和,内核只能杀死另一个进程并释放它的内存,以此来满足下一次的分配需求。

关闭超量使用:

内核允许通过文件/proc/sys/vm/overcommit_memory关闭超量使用,和此功能相似的还有sysctl的vm.overcommit_memory参数。

严格审计策略:

在严格审计模式中,承诺的内存大小被严格限制在交换空间的大小加上可调比例的物理内存大小。

使用严格审计策略时要非常小心!许多系统设计者认为严格审计策略才是解决之道,然而,应用程序常常进行一些不必要的、且只有使用超量使用才能满足的分配请求,而允许这种行为也是设计虚拟内存的主要动机之一。

上一篇 下一篇

猜你喜欢

热点阅读