vxWroks中一个有关互斥的程序

司马青衫依旧 2002-08-02 08:52:10
我看到一个程序,

/*include*/
#include "vxWorks.h"
#include "taskLib.h"
#include "semLib.h"
#include "stdio.h"

/*function prototype*/
void taskOne(void);
void taskTwo(void);

/* global */
#define ITER 10
SEM_ID semBinary;
int global = 0;

void binary(void)
{
int taskIdOne, taskIdTwo;

/* create semphore with available and queue tasks on FIFO basis */
semBinary = semBCreate(SEM_Q_FIFO, SEM_FULL);

/* ----------------NOTE 1--------------*/
semTake(semBinary, WAIT_FOREVER);

/* spawn the two tasks */
taskIdOne = taskSpawn("t1", 90, 0x100, 2000, (FUNCPTR)taskOne, 0,0,0,0,0,0,0,0,0,0);
taskIdTwo = taskSpawn("t2", 90, 0x100, 2000, (FUNCPTR)taskTwo, 0,0,0,0,0,0,0,0,0,0);
}

void taskOne(void)
{
int i;
for (i=0; i<ITER; i++)
{
semTake(semBinary, WAIT_FOREVER);
/* wait indefinitely for semphore */

printf(" I am taskOne and global = %d ...\n", ++global);
semGive(semBinary); /* give up semphore */
}
}

void taskTwo(void)
{
int i;

/*-------------NOTE 2--------------*/
semGive(semBinary); /* give up the semphore and begin the switch */

for (i=0; i<ITER; i++)
{
semTake(semBinary, WAIT_FOREVER);
printf(" I am taskTwo and global = %d ----\n", --lobal);
semGive(semBinary); /* give up semphore */
}
}

这个程序的结果自然是global在1和0之间变化,任务1和任务2不断切换。
但是如果删除上述程序中的注释NOTE1和NOTE2下面的两句,结果是什么呢?我觉得结果不变,但是运行结果是:任务1结束(也就是说循环10次,使得global增加到10),然后才是任务2,global从10减少到0.
我很不理解,任务1semGive之后,任务2应该可以取得信号呀!?
...全文
79 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
wys205 2002-08-05
  • 打赏
  • 举报
回复
Q1:如果taskOne执行的过程中,binary是不是挂起了?
我想你这个问题中的过程有点问题,binary执行完了,taskOne才执行的,没有你说的在taskOne中,binary是不是挂起这种说法,记住,vxWorks是抢占式的内核,如果一个任务没有被阻塞并且没有比它优先级高的任务处于就绪状态,它将一直运行下去。(当vxWorks使用轮转调度--Round-Robin算法时,情况有所不同)
>>这两个任务的优先级比binary高(都是90)
应该是这两个任务的优先级都比binary低,binary的优先级为4,vxWorks是数字越小,优先级越高。
Q2:如果三者的优先级一样,结果会是什么?
优先级一样或binary低的话,结果也是一样。

其实你这些问题和vxWorks关系不大,主要是任务调度和任务间通信的知识,我感觉你对OS的任务调度理解的还不是很透彻,你可以先找一些书看看。我推荐一本:Andrew S.Tanenbaum的《操作系统设计与实现》,国内有译本,王鹏 尤晋元等译。

ipv9 2002-08-05
  • 打赏
  • 举报
回复
suggest you to read vxWorks's getStart.pdf and programmer's guide.
司马青衫依旧 2002-08-05
  • 打赏
  • 举报
回复
我可能有点晕,我问的第一个问题实在不该,想想就算是一般的c程序,也是写在前面的函数运行完之后,写在后面的函数才会运行的。
那我问一问:如果taskOne执行的过程中,binary是不是挂起了?就是说,在不同的时间和不同的优先级他们三个的状态是什么?解释的根据是什么。谢谢!
司马青衫依旧 2002-08-05
  • 打赏
  • 举报
回复
首先我看到大家这么热情,真的非常激动和感谢!分一定多多的给!

我的问题不在于对信号的理解,对同步的理解,对互斥的理解,我想问另外一个问题(我的疑问所在):
(1)
在第一个也就是根任务binary中,spawn了两个任务taksOne和taskTwo,这两个任务的优先级比binary高(都是90),那么如果语句在前的taskOne不挂起,不阻塞的话,是不是要等到taskOne执行完以后,taskTwo才会执行?我想结果是的。根据大家的启发。
(2)
如果三者的优先级一样,结果会是什么?(我自己可以试一试但是,怎么解释?)

最后,非常感谢大家,我刚刚学习嵌入式系统,比较幼稚,希望大家多帮助!
ipv9 2002-08-03
  • 打赏
  • 举报
回复
把程序改成,也可实现交替打印。现在,你该明白问题的答案了。
/*include*/
#include "vxWorks.h"
#include "taskLib.h"
#include "semLib.h"
#include "stdio.h"

/*function prototype*/
void taskOne(void);
void taskTwo(void);

/* global */
#define ITER 10
SEM_ID semBinary;
int global = 0;

void binary(void)
{
int taskIdOne, taskIdTwo;

/* create semphore with available and queue tasks on FIFO basis */
semBinary = semBCreate(SEM_Q_FIFO, SEM_FULL);

/* spawn the two tasks */
taskIdOne = taskSpawn("t1", 90, 0x100, 2000, (FUNCPTR)taskOne, 0,0,0,0,0,0,0,0,0,0);
taskIdTwo = taskSpawn("t2", 90, 0x100, 2000, (FUNCPTR)taskTwo, 0,0,0,0,0,0,0,0,0,0);
}

void taskOne(void)
{
int i;
int flag = 1;

for (i=0; i<ITER; i++)
{
semTake(semBinary, WAIT_FOREVER);
if (flag == 1)
{
taskDelay(10);
flag = 0;
}
printf(" I am taskOne and global = %d ...\n", ++global);
semGive(semBinary); /* give up semphore */
}
}

void taskTwo(void)
{
int i;

for (i=0; i<ITER; i++)
{
semTake(semBinary, WAIT_FOREVER);
printf(" I am taskTwo and global = %d ----\n", --lobal);
semGive(semBinary); /* give up semphore */
}
}

事实上,如果单纯去掉NOTE1和NOTE2的话,任务2在任务1完成前根本不可能执行到semTake()的。
wys205 2002-08-03
  • 打赏
  • 举报
回复
这个例子是《嵌入式实时操作系统VxWorks及其开发环境Tornado》书中的一个例子,其实书上解释的很清楚:
当任务调用semTake()其结果取决于调用时该二进制信号量是否可用,如果可用,信号量将变的不可用,任务继续执行;如果不可用,任务将被挂起,直到信号量可用。
当任务调用semGive()其结果取决于调用时该二进制信号量是否可用,如果可用,本次信号量释放不起任何作用;如果不可用,并且没有任务等待该信号,那么信号量变为可用,如果不可用时,并且有任务等待该信号量,那么阻塞队列的第一个任务解除阻塞,信号量仍不可用。

所以例子中的运行次序是:
1、taskOne调用semTake,OS检查该信号量不可用,所以taskOne阻塞,
2、taskTwo运行,调用semGive(),这时信号量不可用,OS检查是否有阻塞的进程在等待该信号量,显然有taskOne在等待,所以taskOne解除阻塞,注意信号量仍不可用,而当前任务继续运行到semTake,检查信号量仍不可用,taskTwo被挂起。
3、taskOne进入运行状态,继续运行printf(),然后调用semGive(),这时信号量不可用,且有一个任务(taskTwo)在等待该信号量。把taskTwo解除阻塞,继续运行,调用semTake(),然后重复步骤1

去掉两个注释后,
1、信号量出始状态是SEM_FULL,也就是可用的
2、taskOne运行,调用semTake(),发现信号量是可用的,继续执行,信号量变成不可用,运行到semGive(),信号量又变成可用的,于是继续运行。。。
taskTwo只能在taskOne运行完后执行。


Hope this help!:)
starcom13 2002-08-02
  • 打赏
  • 举报
回复
怎么会不变呢。在taskone中,先semtake ,print ,semgive.然后又可以semtake 了,任务不会挂起的,假如你注释了note1 and note 2
直到taskone执行完。
tkit 2002-08-02
  • 打赏
  • 举报
回复
对于同等优先级的任务,信号灯并不能起到强行强占的作用,除非占有资源(信号灯)的任务(也就是任务1)因为某种时间阻塞住了,任务2才可能获取,因为操作系统中的任务调度都是基于事件发生的,或者是任务自己阻塞,或者是更高优先机事件发生,否则的话维持现状
ipv9 2002-08-02
  • 打赏
  • 举报
回复
两任务优先级相同,而task1没有被挂起,所以不会切换到task2。
司马青衫依旧 2002-08-02
  • 打赏
  • 举报
回复
那TaskTwo已经阻塞了呀(因为TaskOne获得了信号),当TaskOne释放信号的时候,TaskTwo应该得到信号呀??这就是我疑惑的原因!

19,502

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧