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应该可以取得信号呀!?
...全文
97 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应该得到信号呀??这就是我疑惑的原因!
【语音分离】基于平均谐波结构建模的无监督单声道音乐声源分离(Matlab代码实现)内容概要:本文介绍了基于平均谐波结构建模的无监督单声道音乐声源分离方法,并提供了相应的Matlab代码实现。该方法通过对音乐信号的谐波结构进行建模,利用音源间的频率特征差异,实现对混合音频不同乐器或人声成分的有效分离。整个过程无需标注数据,属于无监督学习范畴,适用于单通道录音场景下的语音与音乐分离任务。文强调了算法的可复现性,并附带完整的仿真资源链接,便于读者学习与验证。; 适合人群:具备一定信号处理基础和Matlab编程能力的高校学生、科研人员及从事音频处理、语音识别等相关领域的工程师;尤其适合希望深入理解声源分离原理并进行算法仿真实践的研究者。; 使用场景及目标:①用于音乐音频人声与伴奏的分离,或不同乐器之间的分离;②支持无监督条件下的语音处理研究,推动盲源分离技术的发展;③作为学术论文复现、课程项目开发或科研原型验证的技术参考。; 阅读建议:建议读者结合提供的Matlab代码与网盘资料同步运行调试,重点关注谐波建模与频谱分解的实现细节,同时可扩展学习盲源分离的其他方法如独立成分分析(ICA)或非负矩阵分解(NMF),以加深对音频信号分离机制的理解。
内容概要:本文系统介绍了新能源汽车领域智能底盘技术的发展背景、演进历程、核心技术架构及创新形态。文章指出智能底盘作为智能汽车的核心执行层,通过线控化(X-By-Wire)和域控化实现驱动、制动、转向、悬架的精准主动控制,支撑高阶智能驾驶落地。技术发展历经机械、机电混合到智能三个阶段,当前以线控转向、线控制动、域控制器等为核心,并辅以传感器、车规级芯片、功能安全等配套技术。文还重点探讨了“智能滑板底盘”这一创新形态,强调其高度集成化、模块化优势及其在成本、灵活性、空间利用等方面的潜力。最后通过“2025智能底盘先锋计划”的实车测试案例,展示了智能底盘在真实场景的安全与性能表现,推动技术从研发走向市场验证。; 适合人群:汽车电子工程师、智能汽车研发人员、新能源汽车领域技术人员及对智能底盘技术感兴趣的从业者;具备一定汽车工程或控制系统基础知识的专业人士。; 使用场景及目标:①深入了解智能底盘的技术演进路径与系统架构;②掌握线控技术、域控制器、滑板底盘等关键技术原理与应用场景;③为智能汽车底盘研发、系统集成与技术创新提供理论支持与实践参考。; 阅读建议:建议结合实际车型和技术标准进行延伸学习,关注政策导向与行业测试动态,注重理论与实车验证相结合,全面理解智能底盘从技术构想到商业化落地的全过程。
【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)内容概要:本文介绍了名为《【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)》的技术资源,重点围绕电力系统连锁故障的传播路径展开研究,提出了一种N-k多阶段双层优化模型,并结合故障场景筛选方法,用于提升电力系统在复杂故障条件下的安全性与鲁棒性。该模型通过Matlab代码实现,具备较强的工程应用价值和学术参考意义,适用于电力系统风险评估、脆弱性分析及预防控制策略设计等场景。文还列举了大量相关的科研技术支持方向,涵盖智能优化算法、机器学习、路径规划、信号处理、电力系统管理等多个领域,展示了广泛的仿真与复现能力。; 适合人群:具备电力系统、自动化、电气工程等相关背景,熟悉Matlab编程,有一定科研基础的研究生、高校教师及工程技术人员。; 使用场景及目标:①用于电力系统连锁故障建模与风险评估研究;②支撑高水平论文(如EI/SCI)的模型复现与算法验证;③为电网安全分析、故障传播防控提供优化决策工具;④结合YALMIP等工具进行数学规划求解,提升科研效率。; 阅读建议:建议读者结合提供的网盘资源,下载完整代码与案例进行实践操作,重点关注双层优化结构与场景筛选逻辑的设计思路,同时可参考文档提及的其他复现案例拓展研究视野。

19,523

社区成员

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

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