ba_wang_mao 发表于 2010-12-21 09:26:48

uC/OS-ii中,两个任务之间共享资源,请问如何解决谁先发送信号量呢?

(1)、任务1
            voidTaskA (void *pdata)   
         {
            等待信号量;
            程序实体;
            发送信号量;
            }


   (2)、任务2
            voidTaskB (void *pdata)   
         {
            等待信号量;
            程序实体;
            发送信号量;
            }


    多任务运行后,任务A和任务B都请求对方发送信号量,如何解决死锁?(也就是说任务A等待任务B发送信号量,但是任务B又在等待任务A发送信号量,导致死锁)

    解决办法:
            设置等待信号量的TimeOut > 0 , 防止无限等待下去,造成死锁。


   请问:最佳解决办法是什么?

oldtom 发表于 2010-12-21 09:46:42

为什么要采用这种设计呢?

ba_wang_mao 发表于 2010-12-21 10:04:03

信号量有三种工作方式:
      (1)、任务和任务之间的同步
      (2)、中断和任务之间的同步
      (3)、任务之间共享资源

   我所描述的就是任务之间共享资源。

AVR_DIY 发表于 2010-12-21 13:40:59

回复【2楼】ba_wang_mao

   信号量有三种工作方式:
      (1)、任务和任务之间的同步
      (2)、中断和任务之间的同步
      (3)、任务之间共享资源
   我所描述的就是任务之间共享资源。
-----------------------------------------------------------------------

用互斥信号量!
另外,你的这种设计不当!
两个任务用信号量同步应该用以下模式:
(1)、任务1
            voidTaskA (void *pdata)   
         {   
            发送信号量1               
            程序实体;   
            等待信号量2;   
            }


   (2)、任务2
            voidTaskB (void *pdata)   
         {   
            等待信号量1;
            程序实体;   
            发送信号量2;   
            }
这样就不会发生同时等待互相的信号量而死锁!

John_Lee 发表于 2010-12-21 15:43:06

回复【楼主位】ba_wang_mao
-----------------------------------------------------------------------

如果程序仅仅是你的例子一样简单,那么解决方法也很简单,让semaphore的初值为1就可以了,这里的semaphore就是一个token,用于保护共享资源,在运行时,这个token会在所有访问共享资源的任务之间传递,如果某个时刻,没有任务访问共享资源,这个token就呆在semaphore中。

重要的是,这种方式绝不会出现死锁,因为绝不会出现两个任务都在请求semaphore的情况,如果真出现了,那么这个token到哪里去了?有个任务没有释放而再去请求?

你对死锁的概念还没有搞清,只有单一的共享资源的系统中,不会出现死锁。死锁是指两个或多个任务,它们都在请求对方已经拥有的同步对象(semaphore,mutex等),而造成所有任务都进入阻塞状态。

例如:有两个semaphore:sem1(初值为1),sem2(初值为1)。有两个task:task1,task2。

task1
{
   while (1) {
      ...
      pend(sem1);
      ...
      pend(sem2);   // A
      ...
      post(sem1);
      ...
      post(sem2);
}

task2
{
    while (1) {
      ...
      pend(sem2);   // B
      ...
      pend(sem1);   // C
      ...
      post(sem2);
      ...
      post(sem1);
   }
}

当task1运行到了A点时,已经拥有了sem1,正在请求sem2。如果task2此时正好在B点后(已经拥有了sem2),task1就会进入阻塞。而当task2运行到了C点,请求sem1时,由于sem1已经被task1拥有,因此task2也将被阻塞。这样就形成了死锁。

John_Lee 发表于 2010-12-21 16:06:12

回复【3楼】AVR_DIY 苹果的另一半
-----------------------------------------------------------------------

你这样做,不仅帮助不了楼主需要解决共享资源的访问的问题。反而使情况更糟。

“任务1”在“发送信号量1”之后直接访问共享资源,而“任务2”在“等待信号量1”之后,也去访问共享资源。

这样根本没有起到保护共享资源的作用。

ba_wang_mao 发表于 2010-12-21 16:40:11

回复【3楼】AVR_DIY 苹果的另一半
回复【2楼】ba_wang_mao
   信号量有三种工作方式:
      (1)、任务和任务之间的同步
      (2)、中断和任务之间的同步
      (3)、任务之间共享资源
   我所描述的就是任务之间共享资源。
-----------------------------------------------------------------------
用互斥信号量!
另外,你的这种设计不当!
两个任务用信号量同步应该用以下模式:
(1)、任务1
            voidtaska (void *pdata)      
         {   
            发送信号量1               
            程序实体;   
            等待信号量2;   
......
-----------------------------------------------------------------------


      你的写法是错误的,以下是周立功的教材:关于信号量资源共享的流程图描述

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_606121NJ4HLY.JPG
(原文件名:未命名.JPG)



多任务运行后,任务A和任务B都请求对方发送信号量,如何解决死锁?(也就是说任务A等待任务B发送信号量,但是任务B又在等待任务A发送信号量,导致死锁)

    解决办法:
            设置等待信号量的TimeOut > 0 , 防止无限等待下去,造成死锁。


   请问:最佳解决办法是什么?

fwluck 发表于 2010-12-21 16:57:15

很简单。
初始化时赋一个值。就不会,谁也不发而去等。

AVR_DIY 发表于 2010-12-21 17:11:58

回复【6楼】John_Lee
回复【3楼】avr_diy 苹果的另一半
-----------------------------------------------------------------------
你这样做,不仅帮助不了楼主需要解决共享资源的访问的问题。反而使情况更糟。
“任务1”在“发送信号量1”之后直接访问共享资源,而“任务2”在“等待信号量1”之后,也去访问共享资源。
这样根本没有起到保护共享资源的作用。

-----------------------------------------------------------------------

是我理解错了,我以为是两个任务之间实现握手同步!学习了!

回复【7楼】ba_wang_mao
回复【3楼】avr_diy 苹果的另一半
回复【2楼】ba_wang_mao   
   信号量有三种工作方式:   
      (1)、任务和任务之间的同步   
      (2)、中断和任务之间的同步   
      (3)、任务之间共享资源   
   我所描述的就是任务之间共享资源。
-----------------------------------------------------------------------
用互斥信号量!
另外,你的这种设计不当!
两个任务用信号量同步应该用以下模式:
(1)、任务1   
            voidtaska (void *pdata)      
         {   
            发送信号量1               
            程......
-----------------------------------------------------------------------
5楼不是说的很清楚了吗?你单一资源是不会发生死锁的!不然两个都在等待同一个信号量,那么存在的信号量难道“飞”了???

mcu21 发表于 2010-12-21 17:28:22

如果你看过ucos II的源码,你就知道,调用函数OSSemPend等待一个信号量,本质来说,是把调用该函数OSSemPend的任务挂起来。
只要你的程序没有问题,你说的任务1,任务2总有一个会先被执行。

my_avr 发表于 2010-12-21 17:44:20

5楼正解

ba_wang_mao 发表于 2010-12-23 11:50:10

两个任务都要访问全局变量,如何实现资源同步?

多任务运行后,任务A和任务B都请求对方发送信号量,如何解决:
       任务A等待任务B发送信号量,但是任务B又在等待任务A发送信号量,如何解决谁也不会给对方发送信号量?


(1)、任务1
            voidTaskA (void *pdata)   
         {   
            等待信号量;
            程序实体;   
            发送信号量;   
            }


   (2)、任务2
            voidTaskB (void *pdata)   
         {   
            等待信号量;
            程序实体;   
            发送信号量;   
            }



   标准答案:

       在创建信号时,初始值必须为“1”。


http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_606581P56XSS.JPG
(原文件名:任务间使用信号量实现资源同步的一般准则.JPG)

AVR_DIY 发表于 2010-12-23 12:19:47

实现信号量互斥就是要资源共享,初始化为1那是必须的,不然就“没有资源可抢"

Hz01800475 发表于 2012-12-31 12:53:49

学习了
页: [1]
查看完整版本: uC/OS-ii中,两个任务之间共享资源,请问如何解决谁先发送信号量呢?