您尚未登录。

楼主 #1 2018-07-30 17:30:53

mkseven32
会员
注册时间: 2018-04-24
已发帖子: 57
积分: 57

OS 中信号的使用疑问!!!!

这里说的 OS 是CMSIS-OS!

信号操作的三个函数:
int32_t   osSignalSet (osThreadId thread_id, int32_t signals)
int32_t   osSignalClear (osThreadId thread_id, int32_t signals)
osEvent   osSignalWait (int32_t signals, uint32_t millisec)

这里有一篇博客 关于信号的设置和等待说得比较清楚,
https://blog.csdn.net/lh2008xp/article/details/72897954


但是有一点不明白!

Amos_Lee19872017 说:

通知的发送可以从多个任务或者多个中断中发出,但是等待任务通知函数只能有一个。这个地方可能有的人会理解错误,以为只能有一个等待任务通知,其实这里说的是一个任务中只能有一个等待任务通知函数,其他任务中还可以有等待任务通知函数;

这句话怎么理解, 

作为信号的接收方 ,可以是多个任务 同时都在等待接收这个信号?
但是 对应接收信号的 任务,  它只可以有一个等待接收信号  的函数,就是只可以调一次osSignalWait()


这是我做完实验后的理解:
其实应该 就是说 一个任务里面 等待信号到来的 函数最好只有一个地方,(通俗来说就是,一个任务里面最好就调用一个osSignalWait())...

因为,信号产生后,到osSignalWait()处获取到信号后, 接着信号对应的位  系统自己就清了~~~~~
如果是调用两次, 那么等于 任务又被阻塞 。如下代码:          备注 :getSignal_thread1 这个是在一个任务里面一直循环

void getSignal_thread1(void)
{
    osEvent evt;
    evt = osSignalWait(0x1, osWaitForever);
    TRACE("AAAAAAAAAAAAAAAAAAAAAAAAAAAA");
   
    evt = osSignalWait(0x1, osWaitForever);
    TRACE("666666666666666666666666666666");
}


当信号0x01 发送后,进入第一个 osSignalWait(0x1, osWaitForever);  然后解除阻塞,打印AAAAAAAAAA。
打印完 这是信号其实已经被清零了。

而这时有进入了阻塞 osSignalWait(0x1, osWaitForever);   结果又再等信号到来,

这样可能就是 那篇博客 上说的 : 一个任务中只能有一个等待任务通知函数

但是另外一句 :其他任务中还可以有等待任务通知函数

这个就百思不得其解了,  首先发送信号的 函数里面 ,明明就指定了 任务的 id , 说明信号只发给特定的任务,
那么 其他任务中又怎么 可以能接收到该信号呢?


难道 发给任务1 的信号0x01  ,任务2 里面也可以收到?这不是很矛盾吗?


以上是我的理解







下面还有几个疑问:
1.  信号被 接收到之后, 它是不是自动清零呢? 还是需要调用osSignalClear() 手动清零呢?
因为我做了个试验 ,在一个任务里面,做了两个函数,让它们都接收同一个信号。


补充一下我的发送信号函数:
int setsig_func(void)
{
    osThreadSetPriority(getSig_thread1_tid, osPriorityRealtime);
    osSignalSet(getSig_thread1_tid, 0x1);
    return 0;
}

static void process_gesignal(void const *argument)
{
    while(1)
    {
        getSignal_thread1();
        getSignal_thread2();
    }
}

void getSignal_thread1(void)
{
    osEvent evt;
        TRACE("%s",__func__);
    evt = osSignalWait(0x1, osWaitForever);
    TRACE("get signal in thread1");
}

void getSignal_thread2(void)
{
    osEvent evt;
        TRACE("%s",__func__);
    evt = osSignalWait(0x1, osWaitForever);
    TRACE("get signal in thread2");   
}

但是每次 信号触发之后, getSignal_thread1 进来了之后 getSignal_thread2 又可以进来,

这个是不是说明信号被接收之后 它并没有被清零呢?
可是如果没有被清零, 它为什么就只进来一次呢?
那又 是谁 又是在什么时候将它清零呢?

这个错误就是因为 这个打印产生的TRACE("%s",__func__);   其实信号只进入了getSignal_thread1 , 接着打印了 getSignal_thread2 的函数名,然后我误以为进入getSignal_thread2 所以 一直搞不明白, 后来仔细观察 log ,发现不对 怎么getSignal_thread2对比 getSignal_thread1 的 怎么 少了个空格 才恍然大悟~~~~~

所以在这里,奉劝各位坑友!!!做事要仔细,log 别乱加~~~要加也要加有意义的log 不是越多越好~~~ 


2. osSignalClear() 好像没有作用?

我在 接收函数的前面加了一句清零

void getSignal_thread1(void)
{
    osEvent evt;
        TRACE("%s",__func__);
        osSignalClear (getSig_thread1_tid, 0x0f);

    evt = osSignalWait(0x1, osWaitForever);
    TRACE("get signal in thread1");
}

void getSignal_thread2(void)
{
    osEvent evt;
        TRACE("%s",__func__);
         osSignalClear (getSig_thread1_tid, 0x0f);
    evt = osSignalWait(0x1, osWaitForever);
    TRACE("get signal in thread2");   
}
可是信号触发后,还是可以进来~~~~
不但getSignal_thread1 可以, getSignal_thread2 也可以~~~~


这个问题同样和上面一样,因为打印加了个打印函数名,导致误以为进入了getSignal_thread2,

但另外要说的,就是osSignalClear (getSig_thread1_tid, 0x0f); 
其实 第一 这个清零的作用感觉 放在 接收前面不妥, 对于 getSignal_thread1 它的作用其实在信号没产生前它已经执行了,然后阻塞挂起,然后一直在evt = osSignalWait(0x1, osWaitForever); 那里等着, 程序又跑到其他地方去执行了。

所以别老是用 以前单线 直流向下的非OS 系统执行思想 来看到 这种OS 的工作流程,  这是玩OS 必须学会的多线程思想

第二信号在osSignalWait(0x1, osWaitForever); 捕获到之后,它自己本身就清了,也无效你手动调函数 去清~~~~~

于是在getSignal_thread2 中写 osSignalClear (getSig_thread1_tid, 0x0f); 等于 脱裤子放屁, 信号在getSignal_thread1 被 捕获到之后 就清了, 那么在getSignal_thread2 里面又清一次, 不是脱裤子放屁 是什么???


最后感谢 晕哥 和 老发  的热情回复!!!!

真的很高兴有这样一个论坛 可以交流,学习!!!!!

最近编辑记录 mkseven32 (2018-07-31 09:07:23)

离线

楼主 #6 2018-07-31 08:34:49

mkseven32
会员
注册时间: 2018-04-24
已发帖子: 57
积分: 57

Re: OS 中信号的使用疑问!!!!

各位 大神,不好意思!!!,是喔自己 搞错了!!!!我更新一波~~~~

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn