linux 下应用编程进程内存资源的限制

0x01 缘由

  当将生产环境换为64bit后,系统内存的问题全部显现,内存耗尽、内存占用大,导致内存耗尽,吃掉交换分区内存,然后系统卡、卡、卡... ...

0x02 知识点

  linux c 编程资源限制:
  API:  能够通过函数getrlimit()、setrlimit()分别获得、设置每个进程能够创建的各种系统资源的限制使用量。
  命令行:ulimit -a

0x03 TOP显示含义再次学习

VIRT:virtual memory usage 虚拟内存
1、进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等
2、假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量

RES:resident memory usage 常驻内存
1、进程当前使用的内存大小,但不包括swap out
2、包含其他进程的共享
3、如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反
4、关于库占用内存的情况,它只统计加载的库文件所占内存大小

SHR:shared memory 共享内存
1、除了自身进程的共享内存,也包括其他进程的共享内存
2、虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小
3、计算某个进程所占的物理内存大小公式:RES – SHR
4、swap out后,它将会降下来

DATA
1、数据占用的内存。如果top没有显示,按f键可以显示出来。
2、真正的该程序要求的数据空间,是真正在运行中要使用的。

0x03 做法1-进程中调用API

代码:  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/resource.h>  
#include <errno.h>  
#include <iostream>
// 用于内存不足的情况下程序退出
static char *reservedMemoryForExit;

void outOfMemoryHandler()
{
	static bool isInHandler = false;
	if (isInHandler) return;
	isInHandler = true;

	// 释放保留内存,以免程序退出过程中再次出现内存不足
	delete[] reservedMemoryForExit;
	reservedMemoryForExit = NULL;
	printf("Memory Not Enough exit");
	abort();
}


void initNewOperHandler()
{
	const int RESERVED_MEM_SIZE = 1024 * 1024 * 2; // 2M
	std::set_new_handler(outOfMemoryHandler);
	// 用于内存不足的情况下程序退出
	reservedMemoryForExit = new char[RESERVED_MEM_SIZE];
}


int main(void)  
{  
    int nMemoryLimit = 1024 * 1024 * 20;//5M  
  
    struct rlimit64 memoryL;  
  
  	
  
    getrlimit64(RLIMIT_AS, &memoryL);  
    printf("before set mem:%lu,%lu\r\n", (unsigned long)memoryL.rlim_cur, (unsigned long)memoryL.rlim_max);  
  
    memoryL.rlim_cur = nMemoryLimit;  
    memoryL.rlim_max = nMemoryLimit;  
    setrlimit64(RLIMIT_AS ,&memoryL);  
  
    getrlimit64(RLIMIT_AS, &memoryL);  
    printf("after set mem:%lu,%lu\r\n", (unsigned long)memoryL.rlim_cur, (unsigned long)memoryL.rlim_max);  
  
  	initNewOperHandler();
  	
    int i = 0;  
    while(1)  
    {  
        i++;  
        //当进程内存达到最大值时,malloc calloc返回NULL,记录错误errno=ENOMEM  
        errno  = 0;  
        char *psString = (char *)calloc(1, 1024);  
        if(NULL == psString)  
        {  
            printf("errno=%d, ENOMEM=%d\r\n", errno, ENOMEM);  
        }  
        else  
        {  
            printf("success, %d\r\n", i);  
        }  
    }  
    return 0;  
}  

0x04 做法5-利用/proc/pid/status

代码:
{
	char file[64] = { 0 };//文件名
	FILE *fd; //定义文件指针fd
	char lineBuff[256] = { 0 }; //读取行的缓冲区
	sprintf(file, "/proc/%d/status", pid);
	fd = fopen(file, "r"); //以R读的方式打开文件再赋给指针fd

	//获取vmrss:实际物理内存占用
	int i;
	char name[32];//存放项目名称
	int vmrss;//存放内存
	//读取VmRSS这一行的数据
	for (i = 0; i < VMRSS_LINE - 1; i++)
	{
		char* ret = fgets(lineBuff, sizeof(lineBuff), fd);
	}
	char* ret1 = fgets(lineBuff, sizeof(lineBuff), fd);
	sscanf(lineBuff, "%s %d", name, &vmrss);
	fclose(fd); //关闭文件fd
	memTotal = vmrss / 1024;
	return memTotal;
}

0x05 总结

  如果在同一台服务器上需要做资源隔离,可以采用cgroup\taskset等技术完善,内存泄露的问题是必须解决的。以上方法是产品压力较大时的临时解决办法。


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值