5.资源管理

来源:互联网 发布:大数据龙头股票有哪些 编辑:程序博客网 时间:2024/06/03 22:03
    • 资源管理:
      • 各种资源共享方法优劣:

    • 创建临界区方法:
      • 关中断:
        • OS_CFG_ISR_POST_DEFERRED_EN0时,系统以关中断保护临界区;
        • CPU相关函数,而非系统函数,具体在cpu.h文件内;
        • 具体步骤:
          • 临界区前先调用CPU_SR_ALLOC()宏,以分配存储空间存储当前CPU中断状态,具体被存在任务栈内的局部变量CPU_SR内;
          • CPU_CRITICAL_ENTER()将中断标志位存在之前分配空间内,屏蔽可屏蔽中断;
          • 访问临界区的资源,此时的操作即被认为是“原子的”;
          • CPU_CRITICAL_EXIT()恢复之前存储的中断标志位;
        • 说明:
          • 关中断和开中断两个宏必需成对使用,关中断会导致中断延迟时间,影响系统的实时响应;
          • 此种方式是任务和中断服务程序共享变量和数据结构的唯一方法;
          • OS_CRITICAL_ENTER()内调用的是CPU_CRITICAL_ENTER()宏;OS_CRITICAL_EXIT()OS_CRITICAL_EXIT_NO_SCHED()宏;而这些宏用户不应直接访问;

     

    • 禁止任务调度:
      • OS_CFG_ISR_POST_DEFERRED_EN1时,系统尽量以调度器上锁来保护;
      • 具体步骤:
        • 先调用OSSchedLock(&err)关闭任务调度;
        • 访问临界区的代码;
        • 再调用OSSchedUnlock(&err)打开任务调度;
      • 说明:
        • 调度器上锁时,在临界区发生中断,当前代码进栈,中断返回时由于调度器上锁,还会返回当前任务,相当于当前任务变成最高优先级任务,不可抢占;
        • 调度器上锁时,用户不可进行阻塞型调用,否则会导致系统崩溃;
        • 函数OSSchedLock(&err)OSSchedUnlock(&err)可以嵌套250层;

     

    • 信号量:
      • 相关函数(os_sem.c)

    • 信号量类型介绍:
      • os.h内的OS_SEM类型的结构体,当系统OS_CFG_SEN_EN1时则启用;
      • 和定时器等其他内核对象一样,数据结构内有OS_OBJ_TYPE类型的type
      • 有一个指向该信号量的任务挂起表;
      • 有一个表示任务量值的变量OS_SEM_CTR类型的Ctr,其根据资源数量和实际需要进行初始设置;
      • 包含一个记录上次信号量被释放(OSSemPost())的时间戳;
    • 使用过程:
      • 等待信号量OSSemPend(OS_SEM *p_sem,OS_TICK timeout, OS_OPT opt, CPU_TS *p_ts,OS_ERR *p_err)
        • 获取资源的任务先调用此函数,信号量值>0时则获取资源,否则任务进入等待态;
        • 可以设置超时时间,即多少个时钟节拍后任务请求资源失败,重新返回就绪态,此时任务还会被插入时钟节拍表内,设为0时即无限等待;
        • 第三个参数即等待方式:阻塞型(OS_OPT_PEND_BLOCKING)和非阻塞型(OS_OPT_PEND_NON_BLOCKING),后者若信号量无效则立即返回,而不等待,在资源共享中很少用到;
        • 最后的一个error很重要,用于判断任务是否请求到资源,停止等待态的原因;
      • 任务释放信号量OSSemPost(OS_SEM *p_sem,OS_OPT opt,OS_ERR *p_err)
        • 某个任务访问完共享资源后,由此函数释放对应的信号量,此时该函数还会查询等待表看是否有任务等待,没有则Ctr+1
        • 2个参数为OS_OPT_POST_1说明信号量仅释放给一单独任务,此在资源共享时是必需的;
        • 调用此函数时,可以指定不调用调度器;此时即是有新任务进入就绪态也不会触发调度,以便当前任务一次释放所有信号量;
    • 使用说明:
      • 中断程序不能使用信号量,最多只可调用OSSemPost()函数,否则会引起资源共享紊乱,同时,系统运行时不应删除内核对象;
      • 信号量的任务挂起表中任务按照优先级高低顺序排列;
      • 信号量的调用最好可以被封装在底层,即用户调用的只是IO控制函数,里面封装了信号量操作;
      • 信号量最好只用于IO资源共享,而不是内存单元;
      • 获取释放信号量很占时间,过于简单的共享可以直接使用中断;
    • (无界)任务优先级反转:\

    • 如图,低优先级任务L获取了信号量,执行了一段时间后,高优先级任务H进入就绪态;
    • H抢占了内核,但H需要的信号量被L占用,H进入等待态,L继续执行,此即优先级反转;
    • L优先级比较低,而中等优先级任务M等可以随意抢占L,导致L等待,从而导致H等待,致使比较紧急的高优先级任务大量延时;
    • 一种解决方案是:L使用共享资源时先暂时提升其优先级置最高;

     

    • 互斥型信号量-解决优先级反转:
      • 相关函数(os_mutex.c)

    • 优先级反转问题的解决-完全优先级继承:

    • 如图,任务L获取了Mutex,执行了一段时间后,高优先级任务H进入就绪态;
    • H抢占了内核,但H需要的信号量被L占用,系统提升L优先级和H一样,以使L尽快执行完释放Mutex
    • L继续执行到释放Mutex,系统此时恢复L优先级,用户决定是否启用调度器,H获取Mutex进入就绪态;
    • 互斥信号量类型:
      • os.h内的OS_MUTEX类型的结构体,结构体内有一个type类型和一个挂起表;
      • 结构体内OwnerTCBPtr指向占用信号量的任务TCB,在判断嵌套层次时使用;
      • 结构体内OwnerOriginalPrio记录任务占用该信号量前优先级,为解决优先级反转问题后恢复优先级使用;
      • 结构体内Ctr值不为0时即资源被任务占用,系统允许任务多次获取Mutex,而Ctr则是嵌套层数;
      • TS则是用于记录上次被释放时的时间戳;
    • 使用过程:
      • 等待MutexOSMutexPend(OS_MUTEX *p_mutex, OS_TICK timeout,OS_OPTopt, CPU_TS *p_ts, OS_ERR *p_err)
        • timeout即等待超时时间,此时任务还会在时钟节拍表内;
        • optOS_OPT_PEND_NON_BLOCKING时,若信号量被高优先级任务占据,该函数直接返回;被低优先级任务占据,则提升低优先级任务的优先级;
        • optOS_OPT_PEND_BLOCKING时,则该任务被插入Mutex挂起表内;
        • p_err判断是否获取成功和失败的原因,若任务已获取该Mutex,则嵌套层数+1,返回OS_ERR_MUTEX_OWNER
        • 获取成功时会把任务TCB中相关信息放入OS_MUTEX结构体内,并嵌套层数增1
      • 释放MutexOSMutexPost(OS_MUTEX *p_mutex, OS_OPT opt,OS_ERR *p_err)
        • 嵌套层数自减1,若嵌套层数不为0,则返回OS_ERR_MUTEX_NESTING,未真正释放Mutex
        • 若成功释放,结构体内相关的变量都会被复位;
        • 调用此函数时,用户可以设定OS_OPT_POST_NO_SCHED指定不调用调度器;否则自动启用调度器;
    • 使用说明:
      • 和正常信号一样,只有任务才可以使用Mutex,而ISRFunc不可以;
      • 允许任务获取后Mutex进行嵌套,最多250次,因为很多任务不知道自己已多次调用OSMutexPend(),获取与释放应该成对使用;
      • 用户同时只应使用一个Mutex,使用Mutex后便不再使用其他类型的kernel obj
0 0
原创粉丝点击