互斥锁和信号量很相似, RT-Thread 中的互斥锁也有静态和动态之分,和互斥锁有关的
操作如下:
初始化—rt_mutex_init()(对应静态互斥锁);
建立—rt_mutex_create()(对应动态互斥锁);
获取—rt_mutex_take();
释放—rt_ mutex_release();
脱离—rt_mutex_detach()( 对应静态信号量) ;
删除—rt_mutex_delete()( 对应动态信号量);
我们看到信号量和互斥锁如此形似,那么它们的区别在哪里?我以我的理解,区别一下这两个 IPC 对象:
1、信号量哪里都可以释放,但互斥锁只有获得了其控制权的线程才可以释放,即:只有“锁上”它的那个线程才有“钥匙”打开它,有“所有权”的概念。
2、信号量可能导致线程优先级反转,而互斥锁可通过优先级继承的方法解决优先级反转问题(详见《 RT-Thread 编程指南》) 。
实际中我们常遇到这样的情况,比如一个总线上挂接着 N 个设备,这是我们必须“分时”的去操作各个设备,这时候互斥锁就派上用场了:我们在开始操作某个设备前先使用
rt_mutex_take ()锁住总线,然后开始对设备的具体操作,最后通过 rt_mutex_release (),解锁总线,让给其他设备去使用。
信号量用于同步的时候就像交通灯,任务只有在获得许可的时候才可以运行,强调的是运行步骤;信号量用于互斥的时候就像一把钥匙,它强调只有获得钥匙的任务才可以运行,
强调的是许可和权限。这两者都不具备任何数据交换的功能,下面来介绍具有数据交换功能的 IPC 对象: 邮箱和消息队列。
/********************************************************************************************************** * * 模块名称 : 功能演示 * 文件名称 : test.c * 版 本 : V1.0 * 说 明 : * 修改记录 : * 版本号 日期 作者 说明 * * v1.0 2013-4-20 jiezhi320(UP MCU 工作室) 演示互斥锁的基本使用 * * Copyright (C), 2012-2013, * 淘宝店: http://shop73275611.taobao.com * QQ交流群: 258043068 * **********************************************************************************************************/ #include <rtthread.h> #include <stm32f10x.h> #include "test.h" /* 变量分配4字节对齐 */ ALIGN(RT_ALIGN_SIZE) /* 静态线程的 线程堆栈*/ static rt_uint8_t test1_stack[512]; static rt_uint8_t test2_stack[512]; /* 静态线程的 线程控制块 */ static struct rt_thread test1_thread; static struct rt_thread test2_thread; /* 互斥量控制块 */ static struct rt_mutex static_mutex; /* 指向互斥量的指针 */ static rt_mutex_t dynamic_mutex = RT_NULL; void test1_thread_entry(void* parameter) { rt_err_t result; rt_tick_t tick; /* 1. staic mutex demo */ /* 试图持有互斥量,最大等待10个OS Tick后返回 */ rt_kprintf("thread1 try to get static mutex, wait 10 ticks.\n"); /* 获得当前的OS Tick */ tick = rt_tick_get(); result = rt_mutex_take(&static_mutex, 10); if (result == -RT_ETIMEOUT) { /* 超时后判断是否刚好是10个OS Tick */ if (rt_tick_get() - tick != 10) { rt_mutex_detach(&static_mutex); return; } rt_kprintf("thread1 take static mutex timeout\n"); } else { /* 线程2持有互斥量,且在相当长的时间后才会释放互斥量, * 因此10个tick后线程1不可能获得 */ rt_kprintf("thread1 take a static mutex, failed.\n"); rt_mutex_detach(&static_mutex); return; } /* 永久等待方式持有互斥量 */ rt_kprintf("thread1 try to get static mutex, wait forever.\n"); result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER); if (result != RT_EOK) { /* 不成功则测试失败 */ rt_kprintf("thread1 take a static mutex, failed.\n"); rt_mutex_detach(&static_mutex); return; } rt_kprintf("thread1 take a staic mutex, done.\n"); /* 脱离互斥量对象 */ rt_mutex_detach(&static_mutex); /* 2. dynamic mutex test */ /* 试图持有互斥量,最大等待10个OS Tick后返回 */ rt_kprintf("thread1 try to get dynamic mutex, wait 10 ticks.\n"); tick = rt_tick_get(); result = rt_mutex_take(dynamic_mutex, 10); if (result == -RT_ETIMEOUT) { /* 超时后判断是否刚好是10个OS Tick */ if (rt_tick_get() - tick != 10) { rt_mutex_delete(dynamic_mutex); return; } rt_kprintf("thread1 take dynamic mutex timeout\n"); } else { /* 线程2持有互斥量,且在相当长的时间后才会释放互斥量, * 因此10个tick后线程1不可能获得 */ rt_kprintf("thread1 take a dynamic mutex, failed.\n"); rt_mutex_delete(dynamic_mutex); return; } /* 永久等待方式持有互斥量 */ rt_kprintf("thread1 try to get dynamic mutex, wait forever.\n"); result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER); if (result != RT_EOK) { /* 不成功则测试失败 */ rt_kprintf("thread1 take a dynamic mutex, failed.\n"); rt_mutex_delete(dynamic_mutex); return; } rt_kprintf("thread1 take a dynamic mutex, done.\n"); /* 删除互斥量对象 */ rt_mutex_delete(dynamic_mutex); } void test2_thread_entry(void* parameter) { /* 1. static mutex test */ rt_kprintf("thread2 try to get static mutex\n"); rt_mutex_take(&static_mutex, 10); rt_kprintf("thread2 got static mutex\n"); rt_thread_delay(RT_TICK_PER_SECOND); rt_kprintf("thread2 release static mutex\n"); rt_mutex_release(&static_mutex); /* 2. dynamic mutex test */ rt_kprintf("thread2 try to get dynamic mutex\n"); rt_mutex_take(dynamic_mutex, 10); rt_kprintf("thread2 got dynamic mutex\n"); rt_thread_delay(RT_TICK_PER_SECOND); rt_kprintf("thread2 release dynamic mutex\n"); rt_mutex_release(dynamic_mutex); } rt_err_t demo_thread_creat(void) { rt_err_t result; /* 初始化静态互斥量 */ result = rt_mutex_init(&static_mutex, "smutex", RT_IPC_FLAG_FIFO); if (result != RT_EOK) { rt_kprintf("init static mutex failed.\n"); return -1; } /* 创建一个动态互斥量 */ dynamic_mutex = rt_mutex_create("dmutex", RT_IPC_FLAG_FIFO); if (dynamic_mutex == RT_NULL) { rt_kprintf("create dynamic mutex failed.\n"); return -1; } /* 创建test1线程 : 优先级 16 ,时间片 5个系统滴答 */ result = rt_thread_init(&test1_thread, "test1", test1_thread_entry, RT_NULL, (rt_uint8_t*)&test1_stack[0], sizeof(test1_stack), 16, 5); if (result == RT_EOK) { rt_thread_startup(&test1_thread); } /* 创建test2线程 : 优先级 15 ,时间片 5个系统滴答 */ result = rt_thread_init(&test2_thread, "test2", test2_thread_entry, RT_NULL, (rt_uint8_t*)&test2_stack[0], sizeof(test2_stack), 15, 5); if (result == RT_EOK) { rt_thread_startup(&test2_thread); } return 0; }