【uTenux实验】互斥体

【uTenux实验】互斥体

互斥体,维基百科中交互斥锁。其定义是这样的:互斥锁(英语:英语:Mutual exclusion,缩写 Mutex)是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制。该目的通过将代码切片成一个一个的临界区域(critical section)达成。临界区域指的是一块对公共资源进行访问的代码,并非一种机制或是算法。一个程序、进程、线程可以拥有多个临界区域,但是并不一定会应用互斥锁。

关于互斥体,最经典的有两个例子。一个是串口的使用,另一个是打印机的使用。

串口在发送字符串的时候,是不能被中断的。比如发送一个字符串abcdefg,如光刚发完abc时候搞优先级的任务来了,要使用串口发送123456789。这时候如果高优先级任务抢占了低优先级任务对MCU的控制,那么接收端收到的字符串将会是这样的:abc123456789defg。接收到的数据被中断搞混乱了。

再有就是打印机,当低优先级任务在打印时候,刚打印完半页纸,搞优先级任务来了。下半页纸上打出来的将是高优先级任务的数据。整个一张纸上既不是高优先级的东西也不是低优先级任务的东西。

于是就出来了一个互斥体的概念。我使用资源的时候,设置个互斥体将资源锁住,表明正在使用的资源不能被抢断。不管你就绪的任务优先级有多高都得等我用完。

uTenux的互斥体就是一个资源锁。用于确保使用资源的任务不被抢断。

使用优先级继承或者优先级置顶的方法来避免优先级反转。这两种方式,用户不用管,OS已经完全搞定。用户只需要在创建互斥体的时候,告诉OS使用哪种方法即可。

uTenux的互斥体都有一个状态和一个等待锁定互斥体的任务队列

问题:关于创建互斥体函数中的PRI ceilpri 互斥体顶置优先级

函数说明中只有这么一句:仅当TA_CEILING被设置时,ceilpri才有效,才可以设置互斥体的顶置优先级。即使用优先级顶置协议时ceilpri才有效。

我的问题是,香港服务器,ceilpri究竟该怎样设置?设置成所有使用这个互斥他中的最高优先级吗?如果设置的低了会怎样?比如有一个优先级为10的任务使用这个互斥他,而我将ceilpri设置成15.

解答:实验结果是任务的优先级不变化,仍旧保持原有的较高优先级

我想,这里这么用虽然不对,但是也不至于导致系统崩溃。保持原有优先级,虽然可能导致优先级反转的问题,但是系统依旧能够运行。这个算是做软件时候的一个BUG了。

【实验描述】

1、首先创建任务TaskA、TaskB和互斥体MtxID。TaskA和 TaskB优先级相同,都是20。然后启动TaskA。

2、TaskA中首先启动TaskB。两个任务优先级相同,所以此时TaskA具有较高的优先权。TaskB进入就绪等待状态。TaskA继续执行,进入循环体。

3、在循环体中,TaskA首先输出自己当前的优先级,然后锁定Mtx并延时一段时间。最后解锁互斥体。

4、当TaskA解锁互斥体之后,TaskB获得优先权,开始执行。同样TaskB也是先输出优先级然后锁定Mtx之后再次输出优先级。最后解锁互斥体。

5、这个实验使用了支持优先级顶置协议,即任务锁定互斥体之后会将自己的优先级提升到创建互斥体时候设置的级别。

6、使用优先级继承协议在本次实验也有验证,香港虚拟主机,结果是当低优先级任务获得mtx之后并不会被立即提升的优先级,而是当有较高优先级任务请求这个mtx时才会提升优先级。这个实验我在代码中也有

【实验代码和输出】

#include MtxSampleTaskA(W stacd,VP exinf);void MtxSampleTaskB(W stacd,VP exinf);void PutTaskPriority(ID taskid);static ID TaskID_A;static ID TaskID_B;static ID MtxID;ER MtxSample( void){ T_CTSK ctsk; T_CMTX cmtx;tm_putstring((UB*)); cmtx.exinf = NULL; cmtx.mtxatr = TA_TFIFO | TA_CEILING; cmtx.ceilpri = 15; MtxID = tk_cre_mtx(&cmtx);tm_putstring((UB*)); ctsk.bufptr = (VP*)NULL; ctsk.exinf = NULL; ctsk.itskpri = 20; ctsk.stksz = 512; ctsk.task = MtxSampleTaskA; ctsk.tskatr = TA_HLNG | TA_RNG0; TaskID_A = tk_cre_tsk(&ctsk);ctsk.itskpri = 20; tm_putstring((UB*)); ctsk.task = MtxSampleTaskB; TaskID_B = tk_cre_tsk(&ctsk);tm_putstring((UB*)); tk_sta_tsk(TaskID_A,5);return E_OK;}void MtxSampleTaskA(W stacd,VP exinf){ if(E_OK == tk_sta_tsk(TaskID_B,0)) {tm_putstring((UB*)); } while(1) {PutTaskPriority(TaskID_A);tk_loc_mtx(MtxID,-1);tm_putstring((UB*));PutTaskPriority(TaskID_A);Delay(0x1000000);tk_unl_mtx(MtxID);tm_putstring((UB*));PutTaskPriority(TaskID_A);tm_putstring((UB*));//tk_slp_tsk(10); }}void MtxSampleTaskB(W stacd,VP exinf){ while(1) {PutTaskPriority(TaskID_B);tm_putstring((UB*));tk_loc_mtx(MtxID,-1);PutTaskPriority(TaskID_B);tm_putstring((UB*));Delay(0x1000000);PutTaskPriority(TaskID_B);tm_putstring((UB*));tk_unl_mtx(MtxID);PutTaskPriority(TaskID_B);}}void PutTaskPriority(ID taskid){T_RTSK rtsk;ER ercd;B tskpri[10];ercd = tk_ref_tsk(taskid, &rtsk);if(E_OK == ercd){if(taskid == TaskID_A){tm_putstring((UB*));}else{tm_putstring((UB*));}tm_putstring((UB*));ltostr(rtsk.tskpri,tskpri,10,10);tm_putstring((UB*)tskpri);tm_putstring((UB*));}}

一切伟大的行动和思想,都有一个微不足道的开始

【uTenux实验】互斥体

相关文章:

你感兴趣的文章:

标签云: