“你定义了那么多全局变量,系统才给你分配了几百KB,这样做是不是太耗内存了?”,一同学问道。

  老早就听说嵌入式系统各种资源有限啊,不能分配大空间啊要注意节约资源之类的(。。。貌似米神4的配置要完爆我的thinkpad了。。。)。那是不是全局变量的使用真的会占用很大系统内存,而系统真的才分配几百KB空间给我呢?

  我不信,所以我要尝试一下:

  全局变量,肯定是要占用内存的,但无论是不是全局变量,只要是已定义的变量都会占用内存,这个和是否是全局的没啥关系,只是占用的区域不一样而已(详见APUE存储器安排 P153)。

系统怎么可能就给我几百K的空间,那我的安卓机上的QQ咋动不动就几十兆的资源占用率?

  不扯淡了,下面就是我的探究内容。


获得当前进程的堆栈的最大字节长度 :

  1. #define getLimit(name) get_limits(#name,name)
  2. //这个#是字符串创建符,可以在宏中创建字符串
  3.  
  4. //只是打印判断是具体数值还是字符串
  5. void print_infinite(rlim_t t)
  6. {
  7. if(RLIM_INFINITY == t)
  8. {
  9. printf("%14s ","infinite");
  10. }
  11. else
  12. {
  13. printf("%14ld ",t//);
  14. }
  15.  
  16. }
  17.  
  18. //封装了获取特定类型数据的最大值
  19. static void get_limits(char *name,int resource)
  20. {
  21. struct rlimit limit;
  22.  
  23. if(getrlimit(resource,&limit) != )
  24. {
  25. printf("get limit error %s\n",strerror(errno));
  26. }
  27.  
  28. printf("%-14s ",name);
  29.  
  30. print_infinite(limit.rlim_cur);
  31.  
  32. print_infinite(limit.rlim_max);
  33.  
  34. putchar('\n');
  35. }
  36.  
  37. //入口函数,得到进程的堆栈最大值
  38. void GetProcessHeapAndStackLimitSize()
  39. {
  40. printf(PARTING_LINE);
  41.  
  42. printf("%-14s ","Name");
  43. printf("%13s ","LimCur(MB)");
  44. printf("%13s \n","LimMax(MB)");
  45.  
  46. //RLIMIT_DATA 数据段的最大字节长度: 初始化数据、非初始化及堆的总和
  47. getLimit(RLIMIT_DATA);
  48.  
  49. //RLIMIT_STACK 栈区的最大字节长度
  50. getLimit(RLIMIT_STACK);
  51. printf("\n");
  52.  
  53. }

用来测试获取数据是否正确的一个小方法:

递归调用,每调用一次消耗系统 栈区  大小1M。自动变量以及每次函数调用时所需保存的信息都放在区。

  1. //用来测试,是否是堆的最大值
  2. void GetStackSize()
  3. {
  4. static int i = ;
  5.  
  6. char xxx[*] ;///1MB
  7.  
  8. printf("now i is : %d\n",i);
  9.  
  10. GetStackSize(++i);
  11. }

写个main函数,先调用GET方法,获得堆栈值再调用测试函数结果如下:

  1. =============================== GetProcessHeapAndStackLimitSize =================================
  2.  
  3. Name LimCur(MB) LimMax(MB)
  4. RLIMIT_DATA infinite infinite
  5. RLIMIT_STACK infinite
  6.  
  7. now i is :
  8. now i is :
  9. now i is :
  10. now i is :
  11. now i is :
  12. now i is :
  13. now i is :
  14. Segmentation fault (core dumped)

infinite可以理解为不限制,从结果可以看出,当前进程的堆区(其实,这种方法获得的不是严格意义上的堆区,这里获得的是包括初始化数据、非初始化数据及堆区的总和)的大小是

没有限制的,而栈区系统却仅仅分配了8M的空间,也就是说,当前进程下你能使用的局部变量等总和不能超过8M,否则系统就会出现错误(Segmentation Fault)。

如果果真如此的话,那我在main函数里直接定义char xxx[8*1024*1024]会是什么情况呢?显然的,什么都不执行就段错误了。

8M显然是不够我用的,特别是当我需要各种缓冲区时,那我该如何“扩容”呢?或者我系统确实内存有限不能让某些应用程序占用过多内存,那么我如何限制它的内存使用呢?

下面就是修改系统 默认配置的方法:

  1. //封装了设置特定类型数据的最大值
  2. static void set_limits(char *name,int resource,rlim_t cur,rlim_t max)
  3. {
  4. struct rlimit limit;
  5.  
  6. limit.rlim_cur = cur;
  7. limit.rlim_max = max;
  8.  
  9. if(setrlimit(resource,&limit) != )
  10. {
  11. printf("get limit error %s\n",strerror(errno));
  12. }
  13. else
  14. {
  15. printf("%s %s OK \n",__func__,name);
  16.  
  17. }
  18. }
  19.  
  20. void SetProcessHeapAndStackLimitSize()
  21. {
  22. printf(PARTING_LINE);
  23.  
  24. //RLIMIT_DATA 数据段的最大字节长度: 初始化数据、非初始化及堆的总和
  25. rlim_t pref = **;
  26.  
  27. setLimit(RLIMIT_DATA,pref,pref*);
  28.  
  29. //RLIMIT_STACK 栈区的最大字节长度
  30. setLimit(RLIMIT_STACK,pref*,pref*);
  31.  
  32. }

这样设置的结果会什么什么样子呢?我们可以先设置之,然后再重新调用GET方法看看是否设置成功。

  1. //主函数
  2. int main(int argc ,char **argv)
  3. {
  4.  
  5. GetProcessHeapAndStackLimitSize();
  6.  
  7. //GetStackSize();//没有重新设置之前,返回7就崩溃了
  8.  
  9. SetProcessHeapAndStackLimitSize();
  10.  
  11. GetProcessHeapAndStackLimitSize();
  12.  
  13. GetStackSize();//设置后,返回19就崩溃了
  14.  
  15.   ruturn 0;
  16. }

结果如下:

  1. =============================== GetProcessHeapAndStackLimitSize =================================
  2.  
  3. Name LimCur(MB) LimMax(MB)
  4. RLIMIT_DATA infinite infinite
  5. RLIMIT_STACK infinite
  6.  
  7. =============================== SetProcessHeapAndStackLimitSize =================================
  8.  
  9. set_limits RLIMIT_DATA OK
  10. set_limits RLIMIT_STACK OK
  11.  
  12. =============================== GetProcessHeapAndStackLimitSize =================================
  13.  
  14. Name LimCur(MB) LimMax(MB)
  15. RLIMIT_DATA
  16. RLIMIT_STACK
  17.  
  18. now i is :
  19. now i is :
  20. now i is :
  21. now i is :
  22. now i is :
  23. now i is :
  24. now i is :
  25. now i is :
  26. now i is :
  27. now i is :
  28. now i is :
  29. now i is :
  30. now i is :
  31. now i is :
  32. now i is :
  33. now i is :
  34. now i is :
  35. now i is :
  36. now i is :
  37. Segmentation fault (core dumped)

恰如我们所料,修改参数成功,我们可以使用更多的栈区,也可以限制堆区的使用。

而当我们多次执行时却发现一个有趣的现象:虽然我们设置成功了,但重新运行程序后,系统还是会仅仅给我们分配8M,可见我们的这个改变仅仅是对当前进程的设置生效,那么如何对系统所有生效呢?见下文分解。

了解这些东西之后,我们有时可能会碰到程序无故挂掉,任何error信息都不打印,甚至GDB都不说问题出在哪里时,大伙可能得考虑一下,是否被系统限制了。

源码已上传。

探究Linux进程及线程堆栈专题<一>的更多相关文章

  1. Linux进程或线程绑定到CPU

    Linux进程或线程绑定到CPU 为了让程序拥有更好的性能,有时候需要将进程或线程绑定到特定的CPU,这样可以减少调度的开销和保护关键进程或线程. 进程绑定到CPU Linux提供一个接口,可以将进程 ...

  2. Linux进程和线程的比較

    进程与线程 參考:http://www.cnblogs.com/blueclue/archive/2010/07/16/1778855.html 首先比較Linux进程和线程的创建的差别,以此展开: ...

  3. Linux 进程、线程运行在指定CPU核上

    /******************************************************************************** * Linux 进程.线程运行在指定 ...

  4. 巧用Grafana和Arthas自动抓取K8S中异常Java进程的线程堆栈

    前言 近期发现业务高峰期时刻会出现CPU繁忙导致的timeout异常,通过监控来看是因为Node上面的一些Pod突发抢占了大量CPU导致的. 问: 没有限制CPU吗?是不是限制的CPU使用值就可以解决 ...

  5. linux进程、线程与cpu的亲和性(affinity)

    参考:http://www.cnblogs.com/wenqiang/p/6049978.html 最近的工作中对性能的要求比较高,下面简单做一下总结: 一.什么是cpu亲和性(affinity) C ...

  6. Linux进程与线程的区别

    进程与线程的区别,早已经成为了经典问题.自线程概念诞生起,关于这个问题的讨论就没有停止过.无论是初级程序员,还是资深专家,都应该考虑过这个问题,只是层次角度不同罢了.一般程序员而言,搞清楚二者的概念, ...

  7. linux进程与线程的区别【转】

    知乎上总结: "linux使用的1:1的线程模型,在内核中是不区分线程和进程的,都是可运行的任务而已.fork调用clone(最少的共享),pthread_create也是调用clone(最 ...

  8. Linux进程和线程

    一.进程产生的方式 1.描述进程的ID号通常叫做PID,即进程ID,PID的变量类型为pid_t. 2.getpid(void)返回当前进程的ID号,getppid(void)返回当前进程的父进程的I ...

  9. Linux -- 进程或线程独占CPU

    如果想让特定进程或线程独占某一或某些CPU,我们需要做三件事. 一,隔离CPU,避免其它线程run在被隔离的CPU上. 二,绑定所有的interrupts到非隔离的CPU上,避免被隔离的CPU收到in ...

随机推荐

  1. java并发编程:线程安全管理类--原子操作类--AtomicIntegerFieldUpdater<T>

    1.类 AtomicIntegerFieldUpdater<T> public abstract class AtomicIntegerFieldUpdater<T> exte ...

  2. IIS网页GZIP压缩

    1.开GZIP有什么好处? 答:Gzip开启以后会将输出到用户浏览器的数据进行压缩的处理,这样就会减小通过网络传输的数据量,提高浏览的速度. 2.如何启用IIS的Gzip压缩功能: 答:首先,如果你需 ...

  3. 今天廷鹏师弟来的java建议

    如下一段获取数据代码的问题: public Serializable getById(Serializable id) throws BaseBusinessException {  if (id = ...

  4. 用于调试的printf函数和自定义log函数

    1. 用宏定义调试用的DPRINT #define DEBUG_ENABLE #ifdef DEBUG_ENABLE #define DPRINT(fmt, args...) fprintf(stde ...

  5. 2018.12.7 L190

    China called for the immediate release of Meng Wanzhou, chief financial officer of Huawei Technologi ...

  6. ZetCode PyQt4 tutorial layout management

    !/usr/bin/python -*- coding: utf-8 -*- """ ZetCode PyQt4 tutorial This example shows ...

  7. flask第二十四篇——模板【6】自定义过滤器

    请关注孟船长的公众号:自动化测试实战 大家想了解其他过滤器可以参考这里: http://jinja.pocoo.org/docs/dev/templates/#builtin-filters ---- ...

  8. kudu 虚拟机环境使用

      安装 curl -s https://raw.githubusercontent.com/cloudera/kudu-examples/master/demo-vm-setup/bootstrap ...

  9. 使用rollup 开发专业js library

    rollup 是一个不错的javascript 模块打包器,一般我们用来构建library 安装 npm install -g rollup 参考集成jquey && shortid ...

  10. CentOS 6.5 下搭建NTP服务器

    参考网站: http://www.iyunv.com/thread-64847-1-1.html http://acooly.iteye.com/blog/1993484 1         检查系统 ...