ST源码分析-协程局部变量 - 弦外之音

/ 0评 / 0

ST源码分析-st_thread_create》跟 《ST源码分析-内存保护》两篇文章,讲解了,协程函数的栈内存就是下图的区域,如下:



下面就来验证一下协程函数的局部变量是不是真的存储到这块内存区域。还是用 lookupdns 做演示。

首先,在st_thread_create() 函数加上以上代码。

stack->sp = sp - _ST_STACK_PAD_SIZE;
//下面是调试代码。
printf("stack->stk_bottom is %p \r\n",stack->stk_bottom);
printf("stack->sp is %p \r\n",stack->sp);

然后 修改 lookupdns.c 的代码,如下,打印局部变量 addr 的地址。

void *do_resolve(void *host)
{
    struct in_addr addr;
    printf("addr is %p \r\n",&addr);
    ....
    return NULL;
}
​

运行结果如下图:

上图的第一次打印是 idle 协程的,不用管他。

从上图可以看到,addr 的地址,确实在 stack->stk_bottom ~ stack->sp 之间,所以 stack->stk_bottom ~ stack->sp 之间的内存,就是协程函数的栈内存。

do_resolve() 函数里面,定义完 addr 之后,栈顶是 0x7f0114200d44。还剩 0x7f0114200d44 - 0x7f01141f1000 等于 0xFD44 字节。如果我再定义一个变量,超过这个数量的字节,就会触发访问保护内存。演示一下:

我对整个 do_resolve() 都做了修改,因为 printf() 的调用也会占用栈内存。代码如下:

void *do_resolve(void *host)
{
   struct in_addr addr;
    char str[64600] = {0};
    printf("1\r\n");
    return NULL;
}

上图我只定义了 一个 64600 长度的数组,还不够 0xFD44 字节,这是因为函数内部很多操作都会用到栈内存,不只是局部变量。

上图的代码,我运行一下,如下图:

可以正常打印,没问题,所以在我的环境里面 64600 长度的还可以接受,如果是其他的电脑,这个数值会有一点点偏差。

这时候,如果我把 64600 改成 64700 ,加 100 字节,就会里面报错,如下图:

因为访问了收保护的内存,如果真的有需要更大的内存,怎么办?st_thread_create() 函数是有一个参数可以定义申请的栈大小的,如下图,把这个值改大就可以了。


有几种情况,会使用 协程函数的栈内存。

1,协程函数内部调用函数,例如调 printf()

2,协程函数内部使用局部变量。

3,协程函数内部很多操作都会用到 栈内存,一个 if 都有可能用到栈内存。


相关阅读:

  1. 《Linux中mprotect()函数详解》

由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。QQ:2338195090。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注