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

来源:互联网 发布:网络集成商 编辑:程序博客网 时间:2024/06/06 09:27

0x01 缘由

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

0x02 知识点

  内存相关知识点参考http://blog.csdn.net/pangyemeng/article/details/74806620
  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; // 2Mstd::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; //定义文件指针fdchar 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); //关闭文件fdmemTotal = vmrss / 1024;return memTotal;}

0x05 总结

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


阅读全文
0 0
原创粉丝点击