打印

救火车的火灾预警----小心keil的堆栈隐患。

[复制链接]
楼主: 救火车
手机看帖
扫描二维码
随时随地手机跟帖
121
谢谢ayb_ice提醒。这里基本都是搞技术的, 对错大家心中有数。

使用特权

评论回复
122
冷漠| | 2010-7-21 10:18 | 只看该作者

看看51有几个堆栈。

本帖最后由 冷漠 于 2010-7-21 10:33 编辑

LS说的太对了。所长昨天睡觉太早了,没看到冷漠23点发的新帖?好多人昨天就看过了。冷漠的意思是:

PK应该是在对等的平台上,所长一直在裸奔层说事,(说了这么多也没说透彻,一会冷漠再贴2张图给你讲讲什么叫汇编模块的STACK——不是“模块堆栈”啊,别理解错了。也跟老许学点联想理解力。)而冷漠是在操作系统层次上开展证明;——高层、底层,本来就不是一个概念。可惜,所长在下层讲的什么事,冷漠理解得很清楚,而冷漠在上层讲的内容,所长茫然不知。还“概念混乱”给冷漠扣了5个大帽子,真是烧锅炉的斗起了韩美林,——无所不用其极呀。冷漠还以为抄了2段操作系统教材就能提醒所长及时醒悟,可惜所长是一点操作系统概念都没有,一片领域空白。说什么都是一头雾水,更别说暗示了。
      冷漠实在无奈了。

看看51有几个堆栈,128 /256字节内可以有15个私有堆栈,和一个公有堆栈。


使用特权

评论回复
123
ayb_ice| | 2010-7-21 10:52 | 只看该作者
LS
这是TINY OS
每个任务有独立的堆栈,不存在所谓的公有堆栈
TINY OS为了RAM节省空间,会移动堆栈,将所有空闲的RAM分配给当前正在运行的任务当作堆栈,其实就是时间换空间的做法
?STACK就是栈底,也就是第一个任务TASK0的栈底,也是KEIL分配的,这不是什么公有堆栈
为什么说OS下精确定位堆栈安全是扯蛋呢
首先OS下程序调用更复杂,比如用户系统函数进行任务切换可能经过很多层函数才最终实现切换
其次一般OS不提供源代码,多少层调用未知
再其次如果OS支持抢先,情况更糟糕,任务被抢先要占用很多堆栈...
再者局部变量都是保存在任务堆栈中,占用堆栈,调用哪个函数,那么局部就保存在任务堆栈中,不可能限制它调用什么函数
其它原因也很多,不一一列举了
以上不是专门针对TINY OS而言

谈RTOS,我看冷漠连门都没入

....

使用特权

评论回复
124
冷漠| | 2010-7-21 10:54 | 只看该作者
本帖最后由 冷漠 于 2010-7-21 10:58 编辑

这可不是冷漠自创的。杨屹老师想必不陌生吧,听说是21IC出去的?我从他那里随便找了个出处。实际蓝本是国外教材内容,不用冷漠再 上苍穹,下黄泉去找东西了吧。找到了有什么用?所长一句:“断章取义……”冷漠就白干了。要不就是:

“Stallings  这句话有严重的翻译错误,根本就是语病嘛……冷漠的理解完全是误导……”


这是所长给冷漠留下的一贯印象,次数一多,您没说完上句 冷漠就知道您下句要说什么了。这不算个人攻击?你做十分,冷漠才还你一分,你做初一,我做十五。所长一句话,冷漠要做3天的实验来证明,结果证明完了,所长嘻嘻尴尬一笑,走了!完事了?!到底谁错,至少也得道个歉吧,……
冷漠万一做不出来实验结果,所长就来劲了,5个大帽子一起扣……一点都不手软。

这是人干的事?说你心理扭曲有问题,不为过吧?谁还愿意跟你这种人玩?

使用特权

评论回复
125
hqgboy| | 2010-7-21 12:02 | 只看该作者
看看。

使用特权

评论回复
126
冷漠| | 2010-7-21 12:54 | 只看该作者
本帖最后由 冷漠 于 2010-7-21 13:36 编辑

124楼ayb还是那么自信,说话还是那么暂钉截铁。刚输给泠漠一回就又忘了?

每个任务有独立的堆栈,不存在所谓的公有堆栈


呵呵,要不要给你抄一段清华教材上的讲解?当然,你要说国外教材都是放P那就算了。这么简单的概念,还要冷漠在这给RTX高手ayb讲课:

RTX51中每个任务相对51内核来说都是一台虚拟机,都具有自己的独立私有堆栈,(堆栈深度当然可变)这一点你我认知共同,除了私有这个概念。没关系,再往下,一个任务具有3个状态——运行态、就绪态和阻塞态。这不用冷漠教你?听下面:

只有处于运行态的当前活动任务所占有的堆栈才是公有堆栈
冷漠三张图示意的是什么都没看懂,3张图每张中占有最大DATA深度的任务就是当前活动任务,它所占有的堆栈是公有动态活动栈,也即SP所指向的堆栈。——因为所有虚拟机处于运行态时都享有这一堆栈,所以把这一段SP所指向的堆栈称为公共的。(再把弯绕回来,因为这段堆栈是由SP指向的活动堆栈,所以称其为公有(公共)堆栈。)谁愿意称它为A(yb)氏或者所长氏堆栈也没问题。称呼什么是个人自由。

但是任务0堆栈可以占有任务2的堆栈么?跳不过去耶;所以:处于阻塞态和就绪态的任务所占有的堆栈,是静态私有栈。——SP没指向它,它们不是当前活动虚拟机,它们没有占有处理器和SP的权限;你有什么观点概念理由称它为公有活动栈?它连自己的堆栈指针都没有。所以它是静态的静态的。静态的显然不是公共的。呵。ayb硬要说它是公共的,请问它们的SP在哪里?都是同时公有的,一个SP指向谁好?

冷漠当然是RTX51菜鸟,像ayb这样,对玩RTX51 有足够自信的大师,建议也能写一篇“关于51多任务的的堆栈”,比冷漠写的好得多,让冷漠无地自容,才好。
        目前,ayb的**对所长真是一种冷幽默,——51内部多个堆栈讲的清清楚楚。所长对这一点可是完全空白,——所长从来都认为51只有一个堆栈!即SP所指向的那个堆栈,ayb告诉我们大家:51不止只有C51裸奔,还有RTX51操作系统,51操作系统中还有当前不由SP指向的任务堆栈。ayb讲得非常好,给所长上了一堂深刻的OS基础概念课,比冷漠讲得好多了。特别是最后一句结束语:
          欲谈RTOS,我看冷漠连门都没入。那所长还在冷漠后面排队呢。我们都是ayb的学生而已。

       下课。

使用特权

评论回复
127
ayb_ice| | 2010-7-21 13:10 | 只看该作者
本帖最后由 ayb_ice 于 2010-7-21 13:14 编辑

不要混淆视听
那个堆栈就是当前的堆栈,只不过是中断会和当前运行的任务共享堆栈,亦即哪个任务正在运行,中断就会使用哪个任务的堆栈

如果有5个任务,就只有5个堆栈,没有什么额外的公有堆栈

根本就不是你理解的所谓的什么公有堆栈,如果按你的理解那么普通程序也有多个堆栈了
什么前后(中断)堆栈和后台堆栈了...

TINY我5年前就已经在项目使用了

可以告诉你TINY其实有明显BUG,
我还对TINY做了一些改进,当然没有公开

使用特权

评论回复
128
呆板书生| | 2010-7-21 20:35 | 只看该作者
本帖最后由 呆板书生 于 2010-7-21 20:38 编辑

一个简单的测试

#include <intrins.h>
#include <REG52.H>
sfr XXX = 0xFF;
#define TEST__STACK_TIME 220
void main (void)
{
unsigned int ni;
for (ni = 0; ni < TEST__STACK_TIME; ++ni)
{
  _push_(XXX);
}
for (ni = 0; ni < TEST__STACK_TIME; ++ni)
{
  _pop_(XXX);
}
while (1);
}

上述程序在C51通过,运行后,不知道用了多少个堆栈位置呢,运行后,sp_max是多少

如果TEST__STACK_TIME是通过串口进来,编译程序不可能知道是多少,那结果又如何?

使用特权

评论回复
129
highgear| | 2010-7-21 22:04 | 只看该作者
实在佩服冷漠同学的杜撰精神。冷漠同学你贴一个图, 想说明什么? 说明你会贴图?

127搂, 又是一片混乱,不知所云。冷漠你根本不了解scheduler如何操纵sp指针 save/restore context to switch tasks.

原文在此:
http://www.keil.com/support/man/docs/tr51/tr51_stackmgmt.htm

RTX51 Tiny maintains a stack for each task using only the internal memory (IDATA) of the 8051. When a task is running, it is given the maximum amount of stack space possible. When a task switch occurs, the previous task stack is shrunk and relocated and the stack for the current task is expanded and relocated.

使用特权

评论回复
130
highgear| | 2010-7-21 22:28 | 只看该作者
冷漠同学:
要么你给出“静态私有栈“(static private stack) 等等概念的出处, 要么承认是在杜撰。

使用特权

评论回复
131
ayb_ice| | 2010-7-22 08:46 | 只看该作者
LS
我早就说了,他RTOS还没有入门呢

使用特权

评论回复
132
highgear| | 2010-7-22 22:03 | 只看该作者
顶楼上 ayb_ice

使用特权

评论回复
133
甲、乙、丙| | 2010-9-29 10:21 | 只看该作者
25# 救火车 [/顶!

使用特权

评论回复
134
fzu_csc| | 2010-9-29 16:09 | 只看该作者
同意highgear的观点。

按冷漠的说法,那么前台的栈也不止一个了,只要using不同的寄存器组就要有不同的堆栈了,不要把OS的做法强加到keilC51身上。

使用特权

评论回复
135
fzu_csc| | 2010-9-29 16:11 | 只看该作者
不过其实结论自己去试下就会清楚,刚好没空,下班放假了,回去再验证下。

使用特权

评论回复
136
fzu_csc| | 2010-9-29 16:11 | 只看该作者
不过其实结论自己去试下就会清楚,刚好没空,下班放假了,回去再验证下。

使用特权

评论回复
137
jlgcumt| | 2011-12-22 20:34 | 只看该作者
看人吵架也是一种乐趣,哈哈!旧帖翻新!

使用特权

评论回复
138
cmingguo| | 2012-8-8 11:38 | 只看该作者
1# 救火车
1. 51单片机堆栈是向上增长的,当堆栈超过255的时候,SP溢出变为0,将覆盖IDATA内存的低端,导致异常。

2. 估算堆栈大小的方法,可从两个方面着手
    A) 最大函数调用深度,也就是函数里面再调用函数的堆叠深度,每次调用普通函数占用两个字节返回地址压栈
    B) 中断所需现场保护空间,要考虑不同优先级的中断嵌套问题;在中断中也要考虑A)点。

举例:
void fun1()
{
}

void fun2()
{
    fun1();
}

void fun3()
{
    fun2();
}

void fun4()

{
    fun3();
}

void fun5()
{
    fun4();
}
///
void funI1()
{
}

void funI2()
{
    funI1();
}

void funI3()
{
    funI2();
}

void funI4()

{
    funI3();
}

void funI5()
{
    funI4();
}

void InterruptISR() interrupt 0 //如果使用了using,
{
    funI5();
}

void main(void)

{
    while(1)
    {
        fun5();
    }
}

这个例子,主函数那里,需要10个字节堆栈空间;中断函数里面的函数调用需要10个字节堆栈,现场保护,最多13个字节,由于中断函数可能在fun1()函数执行时刻发生,整个程序所需堆栈为33个字节堆栈空间;中断函数使用了USING的话,现场保护减少8个字节,但在227.0那个值会加8

使用特权

评论回复
139
yellowahead| | 2013-2-5 17:43 | 只看该作者
UCOS 跟冷漠说的差不了多少。但这不是讨论51么?

使用特权

评论回复
140
448738516| | 2013-2-5 23:38 | 只看该作者
到底留多少啊????!!!!都在胡扯!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则