Chinaunix首页 | 论坛 | 博客
  • 博客访问: 159725
  • 博文数量: 41
  • 博客积分: 2246
  • 博客等级: 大尉
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-27 15:45
文章分类
文章存档

2012年(4)

2011年(1)

2010年(11)

2009年(25)

分类: LINUX

2009-09-06 16:23:01

   今天突然脑子里面几处知识点大串联,貌似是迸发出了些许思维的火花,以前一直感觉模模糊糊的有关用户栈的大小限制、栈是怎么自动扩展等问题,通过对照以前看过的内核代码的一些关键片段,似乎清晰了起来。机不可失,趁还没迷糊之前拿笔记下来。

问题1    Linux下用户程序的默认
大小是多少?如何查看,又如何更改默认值(上层指令和底层实现)?
   
    在bash中输入“ulimit -s ",就可以查看用户程序的默认栈大小,在我的机器上的结果是(单位为KB)

whodare@whodare:~$ ulimit -s
8192

    修改默认栈大小也很容易

whodare@whodare:~$ ulimit -16384
whodare@whodare:
~$ ulimit -s
16384

    注意,以上的修改只对该bash之后产生成的子进程具有影响,不具备持久性。

    知道了方法,那就来看看有时如何在内核中体现的吧。首先要清楚系统中的每个进程都有一组相关的资源限制,指定了能获取和使用的系统资源的上限,以避免用户过度使用系统资源。

     这样的一组限制在kernel中是通过元素为rlimit结构的数组来实现的,数组的每个元素对应一种资源限制。

    struct rlimit
   {
          unsigned 
long rlim_curr;
          unsigned 
long rlim_max;
     }

     其中rlim_curr表示的是资源限制的当前值(注意不要误解为是资源当前使用量),而rlim_max表示的是资源限制的最大值。前者是软限制,可以 由用户自行修改,只要不超过rlim_max;后者是硬限制,只有管理员才有权限对rlim_max进行更改。

    每个进程的资源限制数组存放在current->signal->rlim字段中,并且资源限制会被子进程自动继承。

    这样就容易理解前面的bash命令了,实质就是读和更新current->signal->rlim[RLIMIT_STACK].rlim_curr的值。

2。栈空间溢出

     如果在函数内部声明了尺寸巨大的数组,很容易会出现栈溢出的错误,即程序运行时提示:"segment error.core dumped"。内核是如何检测到栈溢出的错误呢?

     概括的说,这是通过对缺页异常的处理来完成的。假设我们定义如下一个函数
 
#define SIZE 0x800000

int foo ( )
{

     
char array[SIZE];
        printf("foo");
     
return 0;
}

   
    其中的数组生命通常会被编译器翻译为“ sub 0x800000 %exp",即通过更改ESP来为局部变量分配空间。而对于这里的函数foo,由于这里局部数组的大小和默认栈大小相同(8192KB),因此ESP的值会变为非法,确切的说,在执行完
“ sub 0x800000 %exp"这条语句后,ESP所指向的内存地址不在进程的任何一个合法内存线性区的范围之内;当程序运行到printf()时,会用到ESP进行寻址,这 时候会出现缺页异常,而异常处理程序会根据导致异常发生的不同场景采取不同的处理;对于这个foo函数,缺页异常处理函数会判定属于访问非法地址,因此向 进程发送SIGSEGV信号,导致进程终止执行。

    3.栈的自动扩展

    事实上,当一个程序开始运行时(fork+exec),为其用户栈分配的VMA并不是对应着全部栈空间的,而只是一小部分;随着函数调用的一层层叠加,栈会自动扩展,自动增大栈的当前大小。这也是在缺页异常处理中完成的。
    与前一种情况的区别在于,只有在导致缺页异常的那个线性地址并不比当前esp低很多的情况下,才会调用expand_stack()这个函数来试图扩展栈 空间,而该函数内部调用acct_stack_growth() 来检测是否栈空间已经达到currnent->signal->rlim[RLIMIT_STACK].rlim_curr规定的上限,如果 没有,那么就扩展栈空间,否则同样发送SIGSEGV信号,终止进程。
阅读(1573) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~