【LiteOS】04-开发内核-互斥锁

此笔记由个人整理

华为IOT LiteOS开发实战营

第三天

一、简介

  • 互斥锁又称互斥型信号量,是一种特殊的二型信号量,用于实现对共享资源的独占式处理
  • 任意时刻互斥锁的状态,只有两种:开锁或闭锁
  • 当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权
  • 当该任务释放时,该互斥锁被开锁,任务失去该互斥锁的所有权
  • 当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有
  • 多任务环境下往往存在多个任务竞争统一共享资源的应用场景,互斥锁可被用于对共享资源的保护,从而实现独占式访问。另外互斥锁可以解决信号量存在的优先级翻转问题
  • LiteOS提供的互斥锁具有如下特点:通过优先级继承算法解决优先级翻转问题

二、运作原理

  • 多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理,互斥锁怎么怎样来避免这样的冲突呢?
  • 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁倍加锁状态,此时其他任务如果想访问这个公共资源则会被阻塞。直到互斥锁被持有的该任务释放后,其他任务才能重新访问该公共资源,此时,互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问该公共资源,保证了公共资源操作的完整性。
image-20200527144850895

三、使用场景及开发流程

使用场景

  • 互斥锁可以提供任务之间的互斥机制,用于防止两个任务在同一时刻访问相同的共享资源
  • 互斥锁还可以被用于防止多任务同步时,造成的优先级翻转问题

1、两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作

2、互斥锁不能在中断服务程序中使用

3、尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁

4、有互斥锁的过程中,不得再调用优先级调整等接口函数更改持有互斥锁任务的优先级

开发流程

  • 创建->申请->释放->删除

image-20200527223928633

四、操作系统抽象层

osal_mutex_create(osal_mutex_t *mutex)

image-20200527200955412

osal_mutex_del(osal_mutex_t mutex)

image-20200527201016475

osal_mutex_lock(osal_mutex_t mutex)

image-20200527201031626

osal_mutex_unlock(osal_mutex_t mutex)

image-20200527201043354

五、代码实践

  • 创建工程,选择互斥锁案例

image-20200527203803751

基础实验

  • 代码
#include <osal.h>

#define USER_TASK1_PRI  12//优先级低
#define USER_TASK2_PRI  11//优先级高

uint32_t public_value = 0;//公共值

osal_mutex_t public_value_mutex;  //互斥锁索引id地址

static int user_task1_entry()//任务一
{
    while(1)
    {
        if(true == osal_mutex_lock(public_value_mutex))//判断得到互斥锁
        {
            printf("\r\ntask1: lock a mutex.\r\n");
            public_value += 10;//公共值自加10
            printf("task1: public_value = %ld.\r\n", public_value);
            printf("task1: unlock a mutex.\r\n\r\n");
            osal_mutex_unlock(public_value_mutex);//释放互斥锁
            if(public_value > 100)//如果公共值大于100则退出程序
                break;
            
        }
    }

    return 0;
}
static int user_task2_entry()//任务二
{
    while (1)
    {
       if(true == osal_mutex_lock(public_value_mutex))//判断得到互斥锁
        {
            printf("\r\ntask2: lock a mutex.\r\n");
            public_value += 5; //公共值自加5
            printf("task2: public_value = %ld.\r\n", public_value);
            printf("task2: unlock a mutex.\r\n\r\n");
            osal_mutex_unlock(public_value_mutex);//释放互斥锁
            
            if(public_value > 90)//公共值大于90则退出程序
                break;

            osal_task_sleep(10);
        }
    }

    return 0;
}

int standard_app_demo_main()//主函数
{

    osal_mutex_create(&public_value_mutex);//创建互斥锁
    osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI);//任务一
    osal_task_create("user_task2",user_task2_entry,NULL,0x400,NULL,USER_TASK2_PRI);//任务二

    return 0;
}
  • 结果:task1先创建,但是优先级较低,所以后创建的task2抢占执行,task2获取到互斥锁,对共享资源进行操作,操作完毕解锁,然后主动挂起,task1获取到互斥锁,对共享资源进行另一个操作,操作完毕解锁,在task1操作的时候,task2早已挂起完毕,但是获取不到互斥锁,所以挂起等待,在task1解锁后,阻塞的task2被唤醒开始执行。

image-20200527205457562

image-20200527205510772

扩展实验

  • 1、使用返回值检查函数运行状态

  • 2、加入for循环延时

  • 3、删除互斥锁产生的现象

  • 代码

#include <osal.h>

#define USER_TASK1_PRI  12//优先级低
#define USER_TASK2_PRI  11//优先级高

uint32_t public_value = 0;//公共值

osal_mutex_t public_value_mutex;  //互斥锁索引id地址

static int user_task1_entry()//任务一
{
    while(1)
    {
        if(true == osal_mutex_lock(public_value_mutex))//判断得到互斥锁
        {
            printf("\r\ntask1: lock a mutex OK.\r\n");
            public_value += 10;//公共值自加10
            printf("task1: public_value = %ld.\r\n", public_value);
            printf("task1: unlock a mutex.\r\n\r\n");
            for(uint32_t i=0;i<5000;i++)
            for(uint32_t j=0;j<5000;j++);
            if(true==osal_mutex_unlock(public_value_mutex))
            {
                printf("task1: unlock a mutex OK.\r\n\r\n");
            }
            else
            {
                printf("task1: unlock a mutex ERROR.\r\n\r\n");
            }
            if(public_value > 45)
            {
                if(true==osal_mutex_del(public_value_mutex))
                {
                    printf("task1: del a mutex OK.\r\n\r\n");
                }
                else
                {
                    printf("task1: del a mutex ERROR.\r\n\r\n");
                }
            }
            if(public_value > 100)//如果公共值大于100则退出程序
                break;
        }
        else
        {
            printf("\r\ntask1: lock a mutex ERROR.\r\n");
            osal_task_sleep(1000);
            return 0;
        }
    }

    return 0;
}
static int user_task2_entry()//任务二
{
    while (1)
    {
       if(true == osal_mutex_lock(public_value_mutex))//判断得到互斥锁
        {
            printf("\r\ntask2: lock a mutex OK.\r\n");
            public_value += 5; //公共值自加5
            printf("task2: public_value = %ld.\r\n", public_value);
           	for(uint32_t i=0;i<3000;i++)
            for(uint32_t j=0;j<3000;j++);
            if(true==osal_mutex_unlock(public_value_mutex))
            {
                printf("task2: unlock a mutex OK.\r\n\r\n");
            }
            else
            {
                printf("task2: unlock a mutex ERROR.\r\n\r\n");
            }
            
            if(public_value > 90)//公共值大于90则退出程序
                break;

            osal_task_sleep(10);
        }
        else
        {
            printf("\r\ntask2: lock a mutex ERROR.\r\n");
            osal_task_sleep(1000);
            return 0;
        }
    }

    return 0;
}

int standard_app_demo_main()//主函数
{

    osal_mutex_create(&public_value_mutex);//创建互斥锁
    osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI);//任务一
    osal_task_create("user_task2",user_task2_entry,NULL,0x400,NULL,USER_TASK2_PRI);//任务二

    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值