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

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

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

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

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

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


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

#define getLimit(name) get_limits(#name,name)
//这个#是字符串创建符,可以在宏中创建字符串 //只是打印判断是具体数值还是字符串
void print_infinite(rlim_t t)
{
if(RLIM_INFINITY == t)
{
printf("%14s ","infinite");
}
else
{
printf("%14ld ",t//);
} } //封装了获取特定类型数据的最大值
static void get_limits(char *name,int resource)
{
struct rlimit limit; if(getrlimit(resource,&limit) != )
{
printf("get limit error %s\n",strerror(errno));
} printf("%-14s ",name); print_infinite(limit.rlim_cur); print_infinite(limit.rlim_max); putchar('\n');
} //入口函数,得到进程的堆栈最大值
void GetProcessHeapAndStackLimitSize()
{
printf(PARTING_LINE); printf("%-14s ","Name");
printf("%13s ","LimCur(MB)");
printf("%13s \n","LimMax(MB)"); //RLIMIT_DATA 数据段的最大字节长度: 初始化数据、非初始化及堆的总和
getLimit(RLIMIT_DATA); //RLIMIT_STACK 栈区的最大字节长度
getLimit(RLIMIT_STACK);
printf("\n"); }

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

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

//用来测试,是否是堆的最大值
void GetStackSize()
{
static int i = ; char xxx[*] ;///1MB printf("now i is : %d\n",i); GetStackSize(++i);
}

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

===============================   GetProcessHeapAndStackLimitSize  =================================  

Name                LimCur(MB)      LimMax(MB)
RLIMIT_DATA infinite infinite
RLIMIT_STACK infinite now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
Segmentation fault (core dumped)

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

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

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

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

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

//封装了设置特定类型数据的最大值
static void set_limits(char *name,int resource,rlim_t cur,rlim_t max)
{
struct rlimit limit; limit.rlim_cur = cur;
limit.rlim_max = max; if(setrlimit(resource,&limit) != )
{
printf("get limit error %s\n",strerror(errno));
}
else
{
printf("%s %s OK \n",__func__,name); }
} void SetProcessHeapAndStackLimitSize()
{
printf(PARTING_LINE); //RLIMIT_DATA 数据段的最大字节长度: 初始化数据、非初始化及堆的总和
rlim_t pref = **; setLimit(RLIMIT_DATA,pref,pref*); //RLIMIT_STACK 栈区的最大字节长度
setLimit(RLIMIT_STACK,pref*,pref*); }

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

//主函数
int main(int argc ,char **argv)
{ GetProcessHeapAndStackLimitSize(); //GetStackSize();//没有重新设置之前,返回7就崩溃了 SetProcessHeapAndStackLimitSize(); GetProcessHeapAndStackLimitSize(); GetStackSize();//设置后,返回19就崩溃了   ruturn 0;
}

结果如下:

===============================   GetProcessHeapAndStackLimitSize  =================================  

Name                LimCur(MB)      LimMax(MB)
RLIMIT_DATA infinite infinite
RLIMIT_STACK infinite =============================== SetProcessHeapAndStackLimitSize ================================= set_limits RLIMIT_DATA OK
set_limits RLIMIT_STACK OK =============================== GetProcessHeapAndStackLimitSize ================================= Name LimCur(MB) LimMax(MB)
RLIMIT_DATA
RLIMIT_STACK now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
now i is :
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. js获取当前日期加上30天之后的日期

    var date1 = new Date(); var date2 = new Date(date1); date2.setDate(date1.getDate() + 30); console.lo ...

  2. 新书《Cocos2dx 3.x 3D图形学渲染技术讲解》问世

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  3. PyalgoTrade 打印收盘价(二)

    让我们从一个简单的策略开始,就是在打印收盘价格的过程中: from pyalgotrade import strategy from pyalgotrade.barfeed import yahoof ...

  4. 解决使用SecureCRT出现的Generic clipboard failure错误【自己亲身经历】

    2016年11月8日:[解决办法]把金山词霸卸载了 血的教训浪费了好几个小时 相关文章 1.RecureCRT could not get data from the Clipboard 和SAP快捷 ...

  5. koa/koa2项目搭建

    一键生成koa/koa2项目: 1. npm install -g koa-generator 2.新建项目目录 koa mytest (koa1项目) koa2 koa2test (koa2项目) ...

  6. flow 类型生成工具 flow-typed 简单使用

    flow 是一个javascript 的静态检查工具,flow-typed 为我们提供了三方类似type 的生成 安装flow-typed 使用全局安装 yarn global add flow-ty ...

  7. Spring线程池ThreadPoolTaskExecutor配置及详情

    Spring线程池ThreadPoolTaskExecutor配置及详情 1. ThreadPoolTaskExecutor配置 <!-- spring thread pool executor ...

  8. 【转】foxmail邮箱我已进清理了为什么还是说我的邮箱已满

    原文网址:http://zhidao.baidu.com/link?url=YmX_tBenMVsCopjljd80e2Jwvh7H8GnVSrDLeKKBNQkh_Ty50IsX5eAIy4P_64 ...

  9. rsync 通过密码文件实现远程同步

    https://my.oschina.net/yyping/blog/91964 1.源文件服务器:192.168.10.203 2.备份服务器:192.168.10.88 配置备份服务器(192.1 ...

  10. Sql Server中执行计划的缓存机制

    Sql查询过程 当执行一个Sql语句或者存储过程时, Sql Server的大致过程是 1. 对查询语句进行分析,将其生成逻辑单元,并进行基本的语法检查 2. 生成查询树(会将查询语句中所有操作转换为 ...