打印

uCOS-II中消息邮箱中消息的为局部变量讨论

[复制链接]
16826|56
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Swd21ic|  楼主 | 2008-11-27 21:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
自认为还算比较理解代码的机器级(汇编)表示,但这个把我搞的有点小晕.

首先,一个消息邮箱Post的消息肯定可以是全局或者静态变量,这是肯定没有问题的.

在周航慈老师的书中有一处关于如何存放消息邮箱的讲解.
1. 消息邮箱的消息可以是任务的局部变量, 被同步的任务可以正确的接收.
   大致代码如下:
    void SendTask (void *p_arg)
    {
        INT8U Message;
        Message = 0xFF;
        while (OS_TRUE)
        {
            //将局部变量放入消息邮箱发送
            OSMboxPost(Mbox, (void *)(&Message));  
            OSTimeDly(10);
        }
    }

    void RecTask (void *p_arg)
    {
        INT8U msg

        while(OS_TRUE)
        {
            msg = *(INT8U *)OSMboxPend(Mbox, 0, &err); 
            //任务工作处理
        }
    }
2. 消息邮箱的消息不可以是ISR的局部变量, 被同步的任务不能正确的接收.
   原因是由于ISR结束后,存在栈中的局部变量消失了.
   大致代码如下:
    void ISR (void)
    {
        INT8U Message;
        Message = 8;
        //发送消息邮箱同步任务
        OSMboxPost(Mbox, (void *)(&Message));  
    }

    void RecTask (void *p_arg)
    {
        INT8U msg

        while(OS_TRUE)
        {
            msg = *(INT8U *)OSMboxPend(Mbox, 0, &err); 
            //任务工作处理
        }
    }

先不说我的测试结果,大家讨论一下以上结论是否正确?. 或者有没有补充的一些内容?

相关帖子

沙发
ayb_ice| | 2008-11-27 21:27 | 只看该作者

是这样的

OSMboxPost(Mbox, (void *)(&Message)); 已经把消息的内容复制到了邮箱的专用内存里了。
所以根本不存在你说的问题了,局部变量当然是有生命周期的,这是和标准的C是一样的。

使用特权

评论回复
板凳
jack.king| | 2008-11-27 21:27 | 只看该作者

为什么要使用消息邮箱不能用一个全局变量代替吗?

使用特权

评论回复
地板
ayb_ice| | 2008-11-27 21:33 | 只看该作者

这是操作系统的基本功能

实际是简单的嵌入式系统里用全局变量效率更高

使用特权

评论回复
5
Swd21ic|  楼主 | 2008-11-27 21:41 | 只看该作者

re

消息邮箱可以在多任务间进行行为同步.同时能够传递信息.

而全局变量只能传递信息,但不能同步任务..因此只能用于两种情况.

1)不需要行为同步.想用时就用这个全局变量.  
2)同步要求不实时, 可以让另一个任务定期去查询该全局变量是否被"生产"

使用特权

评论回复
6
学生D| | 2008-11-28 13:43 | 只看该作者

楼上说的有矛盾?

先生自己在一楼说的是“邮箱是全局变量(毋庸置疑)”。怎么又在5楼说:邮箱和全局变量是两回事?

到底邮箱是全局变量还是动态申请的变量?还望麻烦给我们初学者讲讲课。



还有5楼下面这句话把我搞晕了:

“  1)不需要行为同步.想用时就用这个全局变量.  
    2)同步要求不实时, 可以让另一个任务定期去查询该全局变量是否被"生产"  ”

先生说的好像完全不是利用OS操作系统提供的服务来编程,好像是用户自己“裸奔”才这样做。

OS是这样做的:当一个“消费者”需要“生产者”的产品时,他提出索求申请,如果有现成产品,OS交给他取走消费之;如果产品还未生产出来,OS将他排在该产品的专有队列中等待之。一旦有产品生产出来,OS将自动唤醒等待队列中的消费者“提货。”根本不用消费者不停地定期查询“有货吗?”那样显得OS太不作为了。

使用特权

评论回复
7
Swd21ic|  楼主 | 2008-11-28 14:41 | 只看该作者

解释.

首先,阁下误解我在1楼的"一个消息邮箱Post的消息肯定可以是全局或者静态变量"这句话. 我并不是说"邮箱是全局变量"..还是"邮箱所发送的消息可以是全局变量"..用过消息邮箱你肯定会明白我说的是什么.

另外我在5楼说的两点,是针对3楼所说的"用全局变量替代消息邮箱"的问题.那两点根本就没有用到系统的邮箱服务.而是说明什么时候用全局变量可以.这样的情况下当然只能自己去做一些查询的工作,所以说最好用邮箱来同步..




使用特权

评论回复
8
Swd21ic|  楼主 | 2008-11-28 14:43 | 只看该作者

re

今天又对几种情况做了验证.对于"使用局部变量作为邮箱消息"的问题应该已经搞的很明白了. 晚上有空发一下

大家都没有意见么..

使用特权

评论回复
9
machunshui| | 2008-11-28 17:14 | 只看该作者

我的理解

我的理解:

UCOS里面的任务函数和裸奔的一个重要区别是:

UCOS里面的任务函数不会返回,
裸奔函数除了main主函数以外一般都会返回。

UCOS里面的中断函数也是会返回的。

既然UCOS里面的任务函数不会返回,那么UCOS总是能取到任务函数局部变量的指针,

所以,UCOS任务函数的局部变量可以作为消息邮箱的消息。

使用特权

评论回复
10
学生D| | 2008-11-28 17:40 | 只看该作者

周航慈老师的书中概念讲的很清楚,没什么疑问。

2楼解释的也很清楚了。

一个生产者生产的消息产品,是一个局部变量,它在生产车间里(私有堆栈里)放不久的。也就是2楼说的生命周期。它必须及时存放到仓库里,也就是2楼说的把消息及时copy到邮箱“专有内存”里。

在这里,谁是全局变量?谁是局部变量?我觉得没什么不好理解。

使用特权

评论回复
11
学生D| | 2008-11-28 18:01 | 只看该作者

9楼的意思?

9楼的意思是不是说,在消息接收者接收到消息之前,发送消息的当前任务就不会退出?因为它一旦退出,消息就随之消失了。可是还没有确认接收者是否收到了消息?

毕竟邮箱不是打电话,也许接收者正忙于其它重要事。邮箱消息是允许不实时接收的。

实际情景与寄信一样,生产者发给消费者一条消息,并通知消费者到指定的邮箱去取消息。生产着的任务就算完成了,它必须及时退出,让出CPU资源给其他任务。

至于消费者是否收到、什么时候收到该消息,生产者是不会一直等待的。

使用特权

评论回复
12
zyok| | 2008-11-28 18:44 | 只看该作者

我认为:不管消息邮箱的消息是局部变量还是全局变量,都

调用OSMboxPost(OS_EVENT *pevent,void *msg)后就表示该消息还在使用中...
在OSMboxPost()中并没有把消息的内容复制到了邮箱的专用内存里的语句

使用特权

评论回复
13
Swd21ic|  楼主 | 2008-11-28 19:03 | 只看该作者

re

稍微解释一下..晚上还要去打篮球..

关于2楼的
"OSMboxPost(Mbox, (void *)(&Message)); 已经把消息的内容复制到了邮箱的专用内存里了"
其实OSMboxPost的时候并不是把[消息的内容]复制到了邮箱内,而是让邮箱内的消息指针指向了被发送的消息.也就是OSEventPtr内存放的是消息的地址.

9楼说的是对.但我觉得应该考虑更多的情况.细分一下各种情况才能防止出错.
9楼他说的是任务函数不会返回,而不是OSMboxPost不会返回.如果等待该消息的任务优先级高于该任务,则Post不返回就直接进行任务切换了,如果等待消息的任务优先级低于该任务,则直到该任务调用操作系统服务挂起自己后,才能运行.

而且如果很仔细的分析,那么这两种情况下.把函数内的局部变量做为消息发送的结果还不同的.




使用特权

评论回复
14
Swd21ic|  楼主 | 2008-11-28 19:05 | 只看该作者

re

要用个树型图表示各种情况比较好. 花了小半天的时候debug测试才得出的结论.
我觉得挺有意思的.更好的理解了局部变量的生命周期问题.

使用特权

评论回复
15
zyok| | 2008-11-28 19:26 | 只看该作者

请教

具体有什么不同,可否说说
-------------------------------------------------------------------
13L...而且如果很仔细的分析,那么这两种情况下.把函数内的局部变量做为消息发送的结果还不同的.

使用特权

评论回复
16
zyok| | 2008-11-28 21:28 | 只看该作者

难道是...

 void SendTask (void *p_arg)
 {
        INT8U Message;
        Message = 0xFF;
        while (OS_TRUE)
        {
            //将局部变量放入消息邮箱发送
            OSMboxPost(Mbox, (void *)(&Message));  
            OSTimeDly(10);
        }
  }

    void RecTask (void *p_arg)
    {
        while(OS_TRUE)
        {
            OSMboxPend(Mbox, timeout,&err); 
            //任务工作处理
        }
    }
在SendTask()中调用OSMboxPost(Mbox, (void *)(&Message));  发送
&Message,
如果RecTask()在之前已请求过该邮箱,且优先级高于SendTask()
则任务切换到RecTask(),获得Message,并释放SendTask()中变量
如果没有更高优先级的任务等待该消息邮箱,则这个变量会一直保存到有其它任务OSMboxPend(Mbox, timeout,&err) 后才释放...

刚学uCOS-II,基本乱说的...


使用特权

评论回复
17
学生D| | 2008-11-28 21:42 | 只看该作者

同意13楼

“其实OSMboxPost的时候并不是把[消息的内容]复制到了邮箱内,而是让邮箱内的消息指针指向了被发送的消息.也就是OSEventPtr内存放的是消息的地址.”

这是正解。
另外,这是不是足以说明:OSEventPtr所指向的存放消息的首地址内存块是全局变量或者静态变量?
也许还有一种:任务的私有堆栈虽然使用定义上是局部变量,但实际上是静态变量。

使用特权

评论回复
18
wang.ddu| | 2008-11-28 22:24 | 只看该作者

疑问

请问楼主
    void RecTask (void *p_arg)
    {
        while(OS_TRUE)
        {
            OSMboxPost(Mbox, (void *)(&Message)); 
            //任务工作处理
        }
    }
能编译通过,我怎么觉得这个Message像是没有定义的一个东西啊!编译器应该会报错的吧!

使用特权

评论回复
19
Swd21ic|  楼主 | 2008-11-28 22:56 | 只看该作者

re 18楼.

对不起,我写错了.RecTask应该是Pend邮箱的.写成了Post..已经在1楼改正

使用特权

评论回复
20
ayb_ice| | 2008-11-28 23:01 | 只看该作者

OSMboxPost函数到底怎么了消息

这个可以去看源代码。。。

使用特权

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

本版积分规则

71

主题

781

帖子

1

粉丝