嵌入式OS入门笔记_第1页
嵌入式OS入门笔记_第2页
嵌入式OS入门笔记_第3页
嵌入式OS入门笔记_第4页
嵌入式OS入门笔记_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

RTX的进程间通讯主要依赖于四种机制,分别是事件(Event),互斥锁(Mutex),旗语或信号量(Semaphore),和邮箱(Mailbox)。前三种机制侧重进程间的同步,邮箱则侧重进程间的数据通讯。上一篇讲了事件和互斥锁。这次讲一下信号量和邮箱。1.信号量(Semaphore)1.简介信号量其实是一个很抽象的操作系统原语,它最早由荷兰计算机科学家Dijkstra提出,用于解决多项资源的分配问题。实际上信号量的适用范围非常广,可以很好地解决很多问题。简单说来,信号量有三个部分,第一部分就是一个代币容器(一个整形变量),记录着可用的资源数,第二部分就是取用资源(P或者proberen,尝试的荷兰语)的操作,第三个就是还回资源(V或者verhogen,增加的荷兰语)的操作。当资源数量为0时,任何取用资源的操作都会被阻断,直到资源数量增加。刚刚接触可能会觉得跟互斥锁有点难区分,因为RTX中信号量的相关操作跟互斥锁基本一致。先看看怎么使用RTX中的信号量。类似互斥锁,首先要声明一个信号量结构体。OS_SEMsemID;然后需要初始化。os_sem_init(semID,unsignedtoken_count);这里与互斥锁不同的是,你需要指定初始的资源数,token_count,可以是任意非负整数,如果是0,就意味着一开始没有资源可用。然后当你需要取用资源时:os_sen_wait(semID,timeout);timeout的意义就不具体多说了,跟前面介绍的一致。如果成功取用了资源(token_count大于0),那么token_count会减一,并且返回OS_R_OK。如果token_count为0,那么就没办法取用资源,那么这个函数会返回OS_R_SEM,并且进程进入WAIT_SEM状态。当你用完了资源,需要返回资源时,(token_count增加1):os_sem_send(semID);和互斥锁不同的是,当前进程不需要拥有资源,也可以调用该服务,去增加资源数!该服务的中断版本:isi_sem_set(semID);

信号量和互斥锁的区别一般的误区是,信号量用于管理多个只能独享的资源。我们重新考虑上一次提到的场景:整栋房子只有一个公共厕所(共享资源),要使用厕所就要去前台拿钥匙(互斥锁),用完厕所后需要还钥匙给前台。在这种情况下,使用互斥锁机制肯定没问题,那么使用信号量机制会有问题么?如果所有人(进程)都循规蹈矩,那没问题。但如果有人没有去厕所,但也还了一把钥匙给前台,那会发生什么事?那就会有两把钥匙,通向同一个厕所,如果当前有人在上厕所,另外一个人也想要上,前台也会给钥匙给第二个人,那么就会发生尴尬的情况。这个在使用信号量时是有可能的,因为当前进程不需要拥有资源,就能够。s_sem_send!所以哪怕在这种最简单的情况下,也是很有可能误用信号量的。复杂一点的情况,我们考虑如果有两个公共厕所,如果使用互斥锁,那就要声明并初始化两个互斥锁,分别管理两个厕所。那么使用信号量机制,初始化一个os_sem_init(toilet,2);的信号量会不会有问题呢?如果我们不考虑有人恶意还钥匙(os_sem_send误用)的话,好像没问题,因为信号量本身就是为了这样的场景(管理多个独享资源)而设计的?实际上,一样是会有问题的,因为信号量实际上是不区分资源的,而且也不会记录资源使用的顺序。按照我们的例子,也就是说前台会有两把相同的钥匙,任一一把都可以打开两个厕所。假设第一个人去前台拿了一把钥匙,进了厕所A,然后第二个人去前台拿了第二把钥匙,实际上第二个人是无法得知,两个厕所里面有没有人,如果有,是哪一个厕所里面有人。所以,也很有可能会发生尴尬的情况。总的来说,当多个独享资源的先后顺序无关时(例如,生产者和消费者问题),使用信号量才比较合适。或者当进程本身同时是资源的占用者和释放者时,使用互斥锁:[cpp]viewplaincopyOS_MUTmutex;os_mut_init(mutex);..::/*Task1*/os_mut_wait(mutex,0xFFFF);//CriticalSection11.os_mut_release(mutex);

13...15./*Task2*/os_mut_wait(mutex,0xFFFF);18.//CriticalSection20.os_mut_release(mutex);22...当资源的释放者不一定是进程的占用者时,使用信号量:[cpp]viewplaincopyOS_SEMsempahore;os_sem_init(semaphore,0);3...5./*Task1-Producer*/os_sem_wait(semaphore,0xFFFF);//Sendthesignal8...10./*Task2-Consumer*/os_sem_send(semaphore);//Waitforsignal13...几个例子信号量的用法实在是太丰富,而且很容易误用,具体可以参见信号量的用法实在是太丰富,而且很容易误用,具体可以参见《TheLittleBookofSemaphores》和RTX的官方文档,这里摘几个经典的用法(修改过)作为例子:Signaling[cpp]viewplaincopyos_semsemaphore;2.3.__taskvoidtaskl(void){os_sem_init(semaphore,0);while(1){Function1();os_sem_send(semaphore);}}11.12.__taskvoidtask2(void){while(1){os_sem_wait(semaphore,0xFFFF);Function2();}}这个用法是用于保证不同函数的调用顺序(这是C语言很缺乏的一个特征),在这个例子里面,信号量的作用就是确保在每一次调用Function2之前,Functionl都有一次完整的调用。Rendezvous[cpp]viewplaineepyos_semArrived1,Arrived2;2.3.__taskvoidtask1(void){os_sem_init(Arrived1,0);os_sem_init(Arrived2,0);while(1){FunctionA1();os_sem_send(Arrived1);os_sem_wait(Arrived2,0xFFFF);FunctionA2();}

}14.15.__taskvoidtask2(void){while(1){FunctionB1();os_sem_send(Arrived2);os_sem_wait(Arrived1, 0xFFFF);FunctionB2();}}这个用法是更通用的Signaling用法,目的是让FunctionAI,functionBI都完成以后,再执行FunctionA2和FunctionB2。Multiplex[cpp]viewplaincopyos_semMultiplex;__taskvoidtask(void){os_sem_init(Multiplex,5);while(1){os_sem_wait(Multiplex,0xFFFF);Function();os_sem_send(Multiplex);}}这个用法能保证最多只有五个进程能够同时调用Function();更多的例子,请参考上面提到的材料。2.邮箱(Mailbox)1.简介邮箱在RTX中往往是用于在进程间传输大段数据。简单说来,一个邮箱就是一个用户定义长度的队列。队列的每一个单元都是4bytes长,一个单元可以直接保存数据(32位),或者保存一个指针(地址),指向另外一段数据。用邮箱的一个问题就是要用户手动分配内存和回收内存。下面先看看有哪些相关操作。首先要创建一个邮箱,ojmbx_declare(mailbox_name,mail_slots)在RTL.h中有这个的定义,具体是:#defineos_mbx_declare(name,cnt)U32name[4+cnt]也就是说邮箱其实是一个名字为mailbox_name,长度为mail_slots的U32数组。另外注意到,额外的4个slots,是用于管理邮箱的,而不是用来直接存储信息的。创建完邮箱后就要初始化这个邮箱:os_mbx_init(&mailbox_name,sizeof(mailbox_name));发信:os_mbx_send(&mailbox,msg_ptr,timeout)这里的msg_ptr实际上是一个指针,指向需要发送的信息,如果邮箱满了,进程会被阻断,进入WAIT_MBX状态,直到有空间才会返回就绪状态。timeout的用法和前面的timeout一致。同样地,在ISR中有一个相应版本:isr_mbx_send(&mailbox,msg_ptr);这会先调用isr_mbx_check(),去检查邮箱是否已经满了,如果满了就会放弃当前的信息,并且会被陷入os_error();收信:os_mbx_w^it(&mailbox,&msg_ptr,timeout);将收到的信息,存入msg_ptr指向的地址。如果邮箱是空的,进程则会被阻断,进入WAIT_MBX状态,直到有新的信息。ISR的相应版本为:isr_mbx_receive(&mailbox,&msgLptr);BOX内存分配在用邮箱的过程中,会经常涉及到RTX的内存分配问题,如果是变长的内存分配,malloc()和free()这些标准函数可以胜任,但RTX另外提供了一种处理定长内存块的机制-BOX。这里大致简单说一下,具体的用法请参考完整的邮箱例子。_declare_box(box_name,block_size,block_count);_init_box(box_name,box_size,block_size);_alloc_box(box_name);_calloc_box(box_name);_free_box(box_name,)基本上从名字就能知道其意义,和stdlib.h中的标准函数基本对应。—个完整的例子这个例子源于《RL-ARMUser'sGuide》,小幅度修改:[cpp]viewplaincopyos_mbx_declare(MsgBox,16);/*DeclareanRTXmailbox*/U32mpool[16*(2*sizeof(U32))/4+3];/*Reserveamemoryfor16messages*/3.__taskvoidrec_task(void);5.__taskvoidsend_task(void){/*Thistaskwillsenda message. */U32*mptr;os_tsk_create(rec_task, 0);os_mbx_init(MsgBox,sizeof(MsgBox));mptr=_alloc_box(mpool);/*Allocateamemoryforthemessage*/mptr[0]=0x3215fedc;/*Setthemessagecontent.*/mptr[1]=0x00000015;os_mbx_send(MsgBox,mptr,0xffff);/*Sendamessagetoa'MsgBox'*/os_tsk_delete_self();}17.__taskvoidrec_task(void){/*Thistaskwillreceiveamessage.*/U32*rptr,rec_val[2];os_mbx_wait(MsgBox,(void**)&rptr,0xffff);/*Waitforthemessagetoarrive.*/rec_val[0]=rptr[0];/*Storethecontentto

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论