版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
RT-Thread同步机制、优先级继承与临界资源保护第5章信号量与互斥量1、同步与互斥基础2、信号量机制与源码3、互斥量机制与源码4、实验、小结与思考目录CONTENTS信号量互斥量实验回顾概念基础信号量与互斥量的作用03概念基础两类IPC都只传递控制信号,不负责传输消息内容。01信号量协调线程之间或中断与线程之间的执行节奏02互斥量保证临界资源在同一时刻只由一个线程访问03共同基础资源不可用时,线程可进入挂起状态并等待恢复信号量互斥量实验回顾概念基础同步与互斥04概念基础互斥同一时刻只允许一个访问者进入临界区。它限制并发访问,但不规定访问顺序。同步线程按照条件和先后关系协调执行。写入共享资源时通常同时要求互斥。互斥关注能否同时访问,同步关注何时继续执行信号量互斥量实验回顾概念基础信号量与互斥量的区别05概念基础01取值范围信号量可为多值;互斥量在应用层表现为开锁或闭锁02典型用途信号量适合计数和通知;互斥量适合独占资源03所有权信号量无所有者;互斥量记录owner04递归访问信号量不支持;互斥量通过hold记录递归次数05优先级翻转普通信号量无法处理;互斥量使用优先级继承信号量互斥量实验回顾概念基础信号量运作流程06信号量图5.1信号量运作流程图信号量互斥量实验回顾概念基础二值信号量07信号量二值信号量的value只在0和1之间变化。01value=1存在一个可取用的信号,线程可立即通过02value=0没有可用信号,线程根据time决定返回或挂起03release若有人等待则唤醒一个线程,否则value加一04常见场景中断通知线程、两个线程交替执行信号量互斥量实验回顾概念基础中断通知线程08信号量voidadc_isr(void){rt_sem_release(adc_sem);}voidadc_thread(void*parameter){while(1){rt_sem_take(adc_sem,RT_WAITING_FOREVER);process_adc_data();}}01线程没有信号时保持挂起,不轮询flag02中断只释放信号量,缩短中断处理时间03线程恢复后完成耗时的数据处理04信号量承担触发通知,不携带ADC数据信号量互斥量实验回顾概念基础两个线程交替执行09信号量voidthread_a(void*p){while(1){rt_sem_take(sem_a,RT_WAITING_FOREVER);run_stage_a();rt_sem_release(sem_b);}}voidthread_b(void*p){while(1){rt_sem_take(sem_b,RT_WAITING_FOREVER);run_stage_b();rt_sem_release(sem_a);}}初始值决定谁先执行sem_a=1,sem_b=0时,A先运行A完成后释放sem_b,B被唤醒B完成后释放sem_a,下一轮重新开始这种双向同步只用于线程之间信号量互斥量实验回顾概念基础多值信号量10信号量01有限资源计数value表示当前可用资源数,取用时减一,释放时加一02停车场模型初始value等于车位数,value为0时新车辆必须等待或离开03批量唤醒生产者连续释放多个信号,可激活多个等待线程04数值范围控制块使用16位无符号整数,范围为0到65535信号量互斥量实验回顾概念基础信号量控制块11信号量structrt_semaphore{structrt_ipc_objectparent;rt_uint16_tvalue;rt_uint16_treserved;};01parent:包含IPC对象信息和suspend_thread挂起链表02value:当前可利用的信号量数量03reserved:保留字段,当前未使用信号量互斥量实验回顾概念基础value与挂起链表12信号量信号量的关键状态由value和suspend_thread共同表达。01value大于0:申请者直接执行value--,无需切换线程02value等于0:需要等待的申请者进入suspend_thread03释放时有等待者:恢复一个线程,value不增加04释放时无等待者:value增加,但不得超过最大值信号量互斥量实验回顾概念基础rt_sem_init()接口13信号量rt_err_trt_sem_init(rt_sem_tsem,constchar*name,rt_uint32_tvalue,rt_uint8_tflag);参数含义sem静态信号量控制块指针name信号量名称value信号量初始值flag挂起线程按FIFO或优先级排列成功返回RT_EOK,value必须小于0x10000U。信号量互斥量实验回顾概念基础rt_sem_init():对象与链表14信号量RT_ASSERT(sem!=RT_NULL);RT_ASSERT(value<0x10000U);rt_object_init(&(sem->parent.parent),RT_Object_Class_Semaphore,name);rt_ipc_object_init(&(sem->parent));01检查控制块地址和初始值范围02将对象类型登记为Semaphore03初始化IPC公共部分04将suspend_thread初始化为空双向链表信号量互斥量实验回顾概念基础rt_sem_init():初始状态15信号量sem->value=(rt_uint16_t)value;sem->parent.parent.flag=flag;returnRT_EOK;两项赋值决定运行时行为value决定最初有多少次无等待取用机会flag决定多个等待线程的恢复顺序RT_IPC_FLAG_FIFO按进入链表的先后顺序RT_IPC_FLAG_PRIO优先恢复高优先级线程信号量互斥量实验回顾概念基础rt_sem_create()接口16信号量rt_sem_trt_sem_create(constchar*name,rt_uint32_tvalue,rt_uint8_tflag);参数含义name信号量名称value信号量初始值flag挂起线程按FIFO或优先级排列成功返回动态控制块地址,分配失败返回RT_NULL。信号量互斥量实验回顾概念基础静态初始化与动态创建17信号量rt_sem_init()控制块由调用者提供。函数登记静态对象并初始化IPC公共字段。释放时使用rt_sem_detach()。rt_sem_create()函数内部申请控制块内存。分配成功后初始化相同字段。释放时使用rt_sem_delete()。两者的运行机制相同,差别集中在内存和对象生命周期信号量互斥量实验回顾概念基础rt_sem_detach()与rt_sem_delete()18信号量01detach删除静态信号量对象,并恢复所有挂起线程02delete删除动态信号量对象,恢复挂起线程并释放控制块03调用约束对象创建方式必须与删除函数匹配04线程结果等待线程收到对象被删除的错误并重新参与调度信号量互斥量实验回顾概念基础rt_sem_take()接口19信号量rt_err_trt_sem_take(rt_sem_tsem,rt_int32_ttime);参数含义sem目标信号量控制块指针time0为立即返回,正数为限时等待,负数为永久等待成功返回RT_EOK,等待失败通常返回-RT_ETIMEOUT。信号量互斥量实验回顾概念基础rt_sem_take()的三条路径20信号量01快速成功sem->value>0,执行value--后返回02立即失败sem->value==0且time==0,返回-RT_ETIMEOUT03进入等待sem->value==0且time!=0,挂起当前线程04等待结束其他线程释放信号量或线程定时器超时信号量互斥量实验回顾概念基础rt_sem_take():快速成功路径21信号量temp=rt_hw_interrupt_disable();if(sem->value>0){sem->value--;rt_hw_interrupt_enable(temp);}01检查value与执行value--必须处于同一临界区02value大于0表示信号可用03value减一完成取用04恢复中断后直接返回,无需调度信号量互斥量实验回顾概念基础rt_sem_take():不等待路径22信号量if(time==0){rt_hw_interrupt_enable(temp);return-RT_ETIMEOUT;}该分支不会改变线程状态信号量当前不可用调用者明确要求不等待先恢复中断,再返回超时错误适合轮询式检查,但调用者要处理失败结果信号量互斥量实验回顾概念基础rt_sem_take():挂起当前线程23信号量thread=rt_thread_self();thread->error=RT_EOK;rt_ipc_list_suspend(&(sem->parent.suspend_thread),thread,sem->parent.parent.flag);01获取当前线程控制块02清除上一次操作留下的错误码03从就绪队列移出当前线程04按flag规则插入信号量挂起链表信号量互斥量实验回顾概念基础rt_sem_take():定时等待与恢复24信号量if(time>0){rt_timer_control(&thread->thread_timer,RT_TIMER_CTRL_SET_TIME,&time);rt_timer_start(&thread->thread_timer);}rt_hw_interrupt_enable(temp);rt_schedule();if(thread->error!=RT_EOK)returnthread->error;01time大于0时启动线程内置定时器02time小于0时不启动定时器,持续等待03恢复中断后调度其他就绪线程04线程再次运行时检查唤醒原因05超时唤醒时返回-RT_ETIMEOUT信号量互斥量实验回顾概念基础rt_sem_trytake()25信号量rt_err_trt_sem_trytake(rt_sem_tsem){returnrt_sem_take(sem,0);}参数含义sem目标信号量控制块指针它复用rt_sem_take()的不等待路径,资源不可用时立即返回。信号量互斥量实验回顾概念基础rt_sem_release()接口26信号量rt_err_trt_sem_release(rt_sem_tsem);参数含义sem目标信号量控制块指针释放时优先满足等待线程;没有等待者时才增加value。信号量互斥量实验回顾概念基础rt_sem_release():存在等待线程27信号量need_schedule=RT_FALSE;temp=rt_hw_interrupt_disable();if(!rt_list_isempty(&sem->parent.suspend_thread)){rt_ipc_list_resume(&sem->parent.suspend_thread);need_schedule=RT_TRUE;}01关闭中断保护挂起链表02恢复链表中的第一个等待线程03不增加value,相当于把这次释放直接交给等待者04设置need_schedule,稍后统一调度信号量互斥量实验回顾概念基础rt_sem_release():无等待线程28信号量else{if(sem->value<RT_SEM_VALUE_MAX)sem->value++;else{rt_hw_interrupt_enable(temp);return-RT_EFULL;}}rt_hw_interrupt_enable(temp);if(need_schedule==RT_TRUE)rt_schedule();01挂起链表为空时,释放动作累积到value02达到最大值后继续释放会返回-RT_EFULL03先恢复中断,再根据need_schedule调度04应用层仍需限制有效计数范围信号量互斥量实验回顾概念基础rt_sem_control()29信号量rt_sem_control(sem,RT_IPC_CMD_RESET,arg);控制功能与消息队列的reset操作相似重置后恢复等待线程并清理当前状态实际使用前应确认等待线程能处理重置错误信号量互斥量实验回顾概念基础信号量使用注意事项30信号量01避免无界释放不断release会使value偏离实际资源数量02检查take结果只有返回RT_EOK后才能访问受保护资源03不支持递归同一线程重复获取二值信号量可能把自己挂起04成对使用资源计数场景中,每次成功take对应一次release信号量互斥量实验回顾概念基础信号量递归访问会死锁31信号量sem_err1=rt_sem_take(&self_sem,RT_WAITING_FOREVER);if(sem_err1==RT_EOK){critical_work_1();sem_err2=rt_sem_take(&self_sem,RT_WAITING_FOREVER);if(sem_err2==RT_EOK){critical_work_2();rt_sem_release(&self_sem);}rt_sem_release(&self_sem);}第二次take永远等不到本线程后面的release。当没有其他线程释放self_sem时,本线程永久挂起。信号量互斥量实验回顾概念基础递归死锁的状态变化32信号量01初始value=1,第一次take成功,value变为002线程尚未释放信号量,又执行第二次take03value=0且要求永久等待,线程进入suspend_thread04后续release位于同一线程中,但该线程已经无法继续运行05信号量保持为0,临界资源无法再被正常访问信号量互斥量实验回顾概念基础优先级翻转:初始条件33信号量数值越小,RT-Thread线程优先级越高。01线程A高优先级,需要访问临界资源X02线程B中优先级,不访问临界资源X03线程C低优先级,当前持有二值信号量X04关键矛盾A必须等待C释放X,但B可以抢占C信号量互斥量实验回顾概念基础优先级翻转:执行过程34信号量01C取得信号量X,开始处理临界资源02A恢复并申请X,因为X被占用而挂起03B随后恢复,它不需要X,因此抢占仍在运行的C04C要等B运行结束后才能继续并释放X05A间接等待了优先级更低且无关的B信号量互斥量实验回顾概念基础优先级翻转的影响35信号量可接受的等待A等待C完成临界区。C持有A所需的资源,因此这段阻塞具有直接因果关系。不可接受的延长B抢占C,延迟C释放资源。A因而等待了与资源无关且优先级更低的B。互斥量通过优先级继承限制这段额外延迟信号量互斥量实验回顾概念基础互斥量运作流程36互斥量图5.2互斥量运作流程图信号量互斥量实验回顾概念基础互斥量控制块37互斥量structrt_mutex{structrt_ipc_objectparent;rt_uint16_tvalue;rt_uint8_toriginal_priority;rt_uint8_thold;structrt_thread*owner;};相较于信号量,互斥量多记录三类所有权信息。owner:当前持有者hold:递归上锁总数original_priority:持有者的原始优先级信号量互斥量实验回顾概念基础互斥量控制字段38互斥量01value1表示开锁,0表示闭锁02owner指向当前持有互斥量的线程控制块03hold记录同一持有者累计上锁的次数04original_priority保存优先级继承前的线程优先级05suspend_thread保存等待互斥量的线程信号量互斥量实验回顾概念基础rt_mutex_init()接口39互斥量rt_err_trt_mutex_init(rt_mutex_tmutex,constchar*name,rt_uint8_tflag);参数含义mutex静态互斥量控制块指针name互斥量名称flag挂起线程按FIFO或优先级排列初始化成功返回RT_EOK。信号量互斥量实验回顾概念基础rt_mutex_init():建立初始状态40互斥量rt_object_init(&(mutex->parent.parent),RT_Object_Class_Mutex,name);rt_ipc_object_init(&(mutex->parent));mutex->value=1;mutex->owner=RT_NULL;mutex->original_priority=0xFF;mutex->hold=0;mutex->parent.parent.flag=flag;01登记Mutex对象并初始化挂起链表02value=1,互斥量初始开锁03owner=RT_NULL,当前没有持有者04hold=0,没有递归上锁05original_priority设为无效初始值06flag决定等待线程恢复顺序信号量互斥量实验回顾概念基础互斥量的创建与删除41互斥量01rt_mutex_create动态申请控制块并完成与init相同的字段初始化02rt_mutex_detach删除静态互斥量对象并恢复挂起线程03rt_mutex_delete删除动态互斥量对象,随后释放控制块内存04生命周期匹配静态对象使用detach,动态对象使用delete信号量互斥量实验回顾概念基础rt_mutex_take()接口42互斥量rt_err_trt_mutex_take(rt_mutex_tmutex,rt_int32_ttime);参数含义mutex目标互斥量控制块指针time0为立即返回,正数为限时等待,负数为永久等待该函数依赖线程所有权,即使time为0也不能在中断中使用。信号量互斥量实验回顾概念基础rt_mutex_take():递归上锁路径43互斥量thread=rt_thread_self();thread->error=RT_EOK;if(mutex->owner==thread){if(mutex->hold<RT_MUTEX_HOLD_MAX)mutex->hold++;elsereturn-RT_EFULL;}01owner与当前线程相同,说明发生递归访问02不再修改value,它已经处于闭锁状态03只增加hold,记录新增的一层锁04hold达到上限时返回-RT_EFULL信号量互斥量实验回顾概念基础rt_mutex_take():首次取得互斥量44互斥量if(mutex->value>0){mutex->value--;mutex->owner=thread;mutex->original_priority=thread->current_priority;mutex->hold++;}01value从1减为0,完成闭锁02owner记录取得互斥量的线程03保存该线程当前优先级,供释放时恢复04hold从0增为1,表示持有一层锁信号量互斥量实验回顾概念基础rt_mutex_take():不等待失败45互斥量if(time==0){thread->error=-RT_ETIMEOUT;rt_hw_interrupt_enable(temp);return-RT_ETIMEOUT;}互斥量已被其他线程持有不改变owner、hold和value不挂起当前线程恢复中断后立即返回调用者必须根据错误码决定后续处理信号量互斥量实验回顾概念基础rt_mutex_take():优先级继承46互斥量if(thread->current_priority<mutex->owner->current_priority){rt_thread_control(mutex->owner,RT_THREAD_CTRL_CHANGE_PRIORITY,&thread->current_priority);}01当前申请者的优先级高于持有者02临时把持有者提升到申请者的优先级03中间优先级线程不再能够抢占持有者04持有者尽快完成临界区并释放互斥量05继承只改current_priority,original_priority留到解锁时恢复信号量互斥量实验回顾概念基础rt_mutex_take():挂起、定时与恢复47互斥量rt_ipc_list_suspend(&mutex->parent.suspend_thread,thread,mutex->parent.parent.flag);if(time>0){rt_timer_control(&thread->thread_timer,RT_TIMER_CTRL_SET_TIME,&time);rt_timer_start(&thread->thread_timer);}rt_hw_interrupt_enable(temp);rt_schedule();if(thread->error!=RT_EOK)returnthread->error;01当前线程进入互斥量挂起链表02限时等待时启动线程定时器03调度其他就绪线程04恢复运行后检查error05成功获得互斥量时继续执行信号量互斥量实验回顾概念基础rt_mutex_release()接口48互斥量rt_err_trt_mutex_release(rt_mutex_tmutex);参数含义mutex需要释放的互斥量控制块指针只有owner才能释放互斥量,非持有者调用时返回-RT_ERROR。信号量互斥量实验回顾概念基础rt_mutex_release():所有权与hold49互斥量thread=rt_thread_self();if(thread!=mutex->owner){thread->error=-RT_ERROR;rt_hw_interrupt_enable(temp);return-RT_ERROR;}mutex->hold--;01获取调用release的当前线程02检查它是否就是owner03非持有者不能代替owner开锁04检查通过后先减少递归锁层数05hold仍大于0时,互斥量保持闭锁信号量互斥量实验回顾概念基础rt_mutex_release():最终一层锁50互斥量if(mutex->hold==0){if(mutex->original_priority!=mutex->owner->current_priority){rt_thread_control(mutex->owner,RT_THREAD_CTRL_CHANGE_PRIORITY,&mutex->original_priority);}}只有hold归零,最外层临界区才真正结束。此时先把owner的优先级恢复为original_priority,再处理等待线程。信号量互斥量实验回顾概念基础rt_mutex_release():转交所有权51互斥量if(!rt_list_isempty(&mutex->parent.suspend_thread)){thread=rt_list_entry(mutex->parent.suspend_thread.next,structrt_thread,tlist);mutex->owner=thread;mutex->original_priority=thread->current_priority;mutex->hold++;rt_ipc_list_resume(&mutex->parent.suspend_thread);need_schedule=RT_TRUE;}01选择挂起链表中的第一个线程02直接登记新owner,不先value++让所有线程重新竞争03保存新owner的原始优先级04hold设为一层持有状态05恢复线程并延后到函数尾调度信号量互斥量实验回顾概念基础rt_mutex_release():完全开锁52互斥量else{if(mutex->value<RT_MUTEX_VALUE_MAX)mutex->value++;elsereturn-RT_EFULL;mutex->owner=RT_NULL;mutex->original_priority=0xFF;}rt_hw_interrupt_enable(temp);if(need_schedule==RT_TRUE)rt_schedule();01没有等待者时,value恢复为开锁状态02清除owner03重置original_priority04有线程被转交时才执行调度信号量互斥量实验回顾概念基础rt_mutex_control()53互斥量rt_err_trt_mutex_control(rt_mutex_tmutex,intcmd,void*arg){RT_ASSERT(mutex!=RT_NULL);RT_ASSERT(rt_object_get_type(&mutex->parent.parent)==RT_Object_Class_Mutex);return-RT_ERROR;}当前实现只检查对象合法性,随后直接返回-RT_ERROR。信号量互斥量实验回顾概念基础互斥量递归访问54互斥量voidthread_y(void*p){rt_mutex_take(self_mux,RT_WAITING_FOREVER);func();func1();func2();rt_mutex_release(self_mux);}voidfunc(void){rt_mutex_take(self_mux,RT_WAITING_FOREVER);update_shared_state();rt_mutex_release(self_mux);}thread_y和func使用同一个互斥量。第二次take的owner仍是当前线程,因此只增加hold,不会把自己挂起。信号量互斥量实验回顾概念基础递归锁保护跨函数操作55互斥量01thread_y取得最外层锁,hold=102func再次取同一互斥量,hold=203func更新共享数据后release,hold回到104func1和func2继续处理同一批共享数据05thread_y最后release,hold=0,互斥量才真正开锁这种写法适合公共函数自身要保证安全,而上层调用者又要扩大临界区范围的场景。信号量互斥量实验回顾概念基础信号量实验:按键触发LED56实验回顾01初始化创建key2led,初始value=0,等待方式为FIFO02LED线程永久等待key2led,获得信号后翻转LED电
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 大学计算机与人工智能 课件全套 薛丽丽 第1-7章 计算机与信息技术基础 -大数据技术
- 新教材高中历史 第二单元 中古时期的世界 第4课 中古时期的亚洲教学教学设计 新人教版必修《中外历史纲要(下)》
- 小学信息技术第二册上 第十三课综合实践教案 泰山版
- 高中物理 4.3 牛顿第二定律教学设计 新人教版必修1
- 上海市理工大学附属中学-学年高一体育上学期第2周教学设计2
- 形色协奏曲(教学设计)湘美版(2012)美术六年级下册
- 湖南省初中体育 12 跑教案
- 小学美术人美版四年级下册11.认识中国画教学设计
- 粤教版 信息技术 必修 3.1.2日常文本信息的加工与表达教学设计
- 九年级化学下册 第8单元《课题1 金属材料》教学设计4 (新版)新人教版
- GB/T 17421.2-2016机床检验通则第2部分:数控轴线的定位精度和重复定位精度的确定
- 2021年江苏省普通高中学业水平合格性考试物理(样卷及答案)
- 再生资源循环回收利用及新型模式探讨概述课件
- 部编人教版六年级道德与法治上册全册教学课件
- 《中药炮制技术》 教学课件大全
- 课程市场信息学(完整版适合电子商务相关方面的朋友)
- 泄漏电流能力验证终期报告
- ISO15189质量体系同济医院检验科ISO15189体系文件-质量手册
- 24度锥接头设计
- 水进、水退、吉尔伯特型湖波扇三角洲亚相和微相的特征
- 公路路基土石方工程施工技术方案(最全面)
评论
0/150
提交评论