本帖最后由 gjianw217 于 2015-10-25 15:45 编辑
在本帖子中,主要分析一下庆科MiCO RTOS的互斥锁,具体包括:
OS互斥锁
MiCO互斥锁关键API
MiCO互斥锁示例
MiCO互斥锁测试结果
一、OS互斥锁
上篇分析了信号量,而互斥锁,是一种特殊的信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源。可以保证以下三点:
原子性:把一个互斥量锁定为一个原子操作,这意味着操作系统(或pthread函数库)保证了如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量。
唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量。
非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。
从以上三点,我们看出可以用互斥量来保证对变量(关键的代码段)的排他性访问。即信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源。比如对全局变量的访问,有时要加锁,操作完了,在解锁。有的时候锁和信号量会同时使用。
二、MiCO 互斥锁关键API
在MiCO中,对于互斥锁的定义,位于SDK_MiCOKit_v2.3.0.2includemico_rtos.h中,主要有以下函数:
其中,常用的有:
(1)OSStatus mico_rtos_init_mutex(mico_mutex_t* mutex );
该函数为初始化一个互斥锁,参数为指向要初始化的互斥锁的句柄的指针(typedef void* mico_mutex_t;)
(2)OSStatus mico_rtos_lock_mutex(mico_mutex_t* mutex );
该函数为获得一个互斥锁,参数为指向要获取的互斥锁的句柄的指针
(3)OSStatus mico_rtos_unlock_mutex(mico_mutex_t* mutex );
该函数为释放一个互斥锁,参数为指向要释放的互斥锁的句柄的指针
三、MiCO互斥锁示例
该示例参数官方的测试demo,参考示例代码位于SDK_MiCOKit_v2.3.0.2DemosCOM.MXCHIP.BASICos,官网示例代码说明http://mico.io/wiki/doku.php?id=basic_os。该示例为一个经典的生产者与消费者模型,一个线程负责生产,一个线程负责消费,由互斥量保证全局变量每次只有一个线程“拥有”。
- mico_mutex_t mutex = NULL;
- int g_tickets = 1;//
- char *p_name1 = "consumption";
- char *p_name2 = "production";
- void mutex_consumption(void *arg)//
- {
- char *name = (char *)arg;
- while(1){
- mico_rtos_lock_mutex(&mutex);
- if(g_tickets==1)
- {
- mico_os_log( "Thread exit %s",name );;
- g_tickets=0;
- }
- mico_rtos_unlock_mutex(&mutex);
- }
- }
- void mutex_production(void *arg)
- {
- char *name = (char *)arg;
- while(1){
- mico_rtos_lock_mutex(&mutex);
- if(g_tickets==0)
- {
- mico_os_log( "Thread exit %s",name );;
- g_tickets=1;
- }
- mico_rtos_unlock_mutex(&mutex);
- }
- }
- void TestMiCOMutex(void)
- {
- OSStatus err = kNoErr;
- /* Create a mutex*/
- err = mico_rtos_init_mutex( &mutex);
- require_noerr(err, exit);
- /* Create threads */
- err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY+1, "consumption", mutex_consumption, 0x800, p_name1 );
- require_noerr(err, exit);
- err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY+1, "production", mutex_production, 0x800, p_name2 );
- require_noerr(err, exit);
- exit:
- if( err != kNoErr )
- mico_os_log( "Thread exit with err: %d", err );
- mico_rtos_delete_thread(NULL);
- }
四、MiCO示例效果