当前位置: 首页 > news >正文

企业网站管理系统 开源营销公司取名字大全

企业网站管理系统 开源,营销公司取名字大全,如何做点击图片转到其他网站,网站建设需要匹配人员目录 前言 一、互斥量概述 二、互斥量函数 1.创建 2.其他函数 三、优先级反转示例 1.概念 2.代码示例 四、优先级继承 1.概念 2.代码示例 五、递归锁 1.死锁的概念 2.自我死锁 3.函数 4.递归锁代码示例 前言 在之前的信号量中,我们想要实现互斥的…

目录

前言

一、互斥量概述

二、互斥量函数

1.创建

2.其他函数

三、优先级反转示例

1.概念

2.代码示例

四、优先级继承 

1.概念

2.代码示例

五、递归锁

1.死锁的概念

2.自我死锁

3.函数

4.递归锁代码示例


前言

在之前的信号量中,我们想要实现互斥的效果,即独占的享用临界资源,假设厕所临界资源,怎么独占?自己开门上锁,完事了自己开锁。

但是freeRTOS的信号量并没有实现自己上的锁只能自己开这个功能,要想实现互斥,必须要有个前提条件:

        \bullet 没有坏人:别的任务不会"give"信号量(不撬门)

在我之前的文章关于Linux系统的互斥锁中,举得代码例子也是凭空拿了一把锁,这就说明要想通过信号量来实现互斥,需要程序员自己约定。


一、互斥量概述

可以看到,使用信号量确实也可以实现互斥访问,但是不完美。

使用互斥量可以解决这个问题,互斥量的名字取得很好:
        \bullet 量:值为0、1
        \bullet 互斥:用来实现互斥访问
它的核心在于:谁上锁,就只能由谁开锁。

很奇怪的是,FreeRTOS的互斥锁,并没有在代码上实现这点:
        \bullet 即使任务A获得了互斥锁,任务B竟然也可以释放互斥锁。
        \bullet 谁上锁、谁释放:只是约定。

互斥锁解决的核心问题其实是优先级反转优先级继承

互斥量其实就是一种特殊的二进制信号量,只不过它能解决优先级反转和实现优先级继承。


二、互斥量函数

1.创建

使用互斥量时,先创建、然后去获得、释放它。使用句柄来表示一个互斥量。

创建互斥量的函数有2种:动态分配内存,静态分配内存,函数原型如下:

/* 创建一个互斥量,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutex( void );/* 创建一个互斥量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个StaticSemaphore_t结构体,并传入它的指针
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer
);

要想使用互斥量,需要在配置文件FreeRTOSConfig.h中定义:

#define configUSE_MUTEXES 1

注意:二级制信号量初始值是0,创建后需要Give一次;互斥量初始值是1,创建后不需要Give一次。 

2.其他函数

要注意的是,互斥量不能在ISR中使用。

各类操作函数,比如删除、give/take,跟一般是信号量是一样的。

/*
* xSemaphore: 信号量句柄,你要删除哪个信号量, 互斥量也是一种信号量
*/
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );/* 释放 */
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );/* 获得 */
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait
);

三、优先级反转示例

1.概念

假设任务A、B都想使用串口,A优先级比较低:
        \bullet 任务A获得了串口的互斥量
        \bullet 任务B也想使用串口,它将会阻塞、等待A释放互斥量
        \bullet 高优先级的任务,被低优先级的任务延迟,这被称为"优先级反转"(priority inversion)

互斥量可以通过"优先级继承",可以很大程度解决"优先级反转"的问题,这也是FreeRTOS中互斥量和二进制信号量的差别。

2.代码示例

main函数创建了3个任务:LPTask/MPTask/HPTask(低/中/高优先级任务),代码如下:

/* 互斥量/二进制信号量句柄 */
SemaphoreHandle_t xLock;
int main( void )
{prvSetupHardware();/* 创建二进制信号量!!!!!! */xLock = xSemaphoreCreateBinary();if( xLock != NULL ){/* 创建3个任务: LP,MP,HP(低/中/高优先级任务)*/xTaskCreate( vLPTask, "LPTask", 1000, NULL, 1, NULL );xTaskCreate( vMPTask, "MPTask", 1000, NULL, 2, NULL );xTaskCreate( vHPTask, "HPTask", 1000, NULL, 3, NULL );/* 启动调度器 */vTaskStartScheduler();}else{/* 无法创建互斥量/二进制信号量 */}/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */return 0;
}

注意:创建的是二进制信号量,用于演示优先级反转!!!

LPTask/MPTask/HPTask三个任务的代码和运行过程如下图所示:

\bullet A:HPTask优先级最高,它最先运行。在这里故意打印,这样才可以观察到flagHPTaskRun的脉          冲。
\bullet HP Delay:HPTask阻塞
\bullet B:MPTask开始运行。在这里故意打印,这样才可以观察到flagMPTaskRun的脉冲。
\bullet MP Delay:MPTask阻塞
\bullet C:LPTask开始运行,获得二进制信号量,然后故意打印很多字符
\bullet D:HP Delay时间到,HPTask恢复运行,它无法获得二进制信号量,一直阻塞等待
\bullet E:MP Delay时间到,MPTask恢复运行,它比LPTask优先级高,一直运行。导致LPTask无法             运行,自然无法释放二进制信号量,于是HPTask无法运行。

总结:
\bullet LPTask先持有二进制信号量
\bullet 但是MPTask抢占LPTask,LPTask一直无法运行也就无法释放信号量
\bullet 导致HPTask任务无法运行
\bullet 优先级最高的HPTask竟然一直无法运行!

程序运行的时序图如下:


四、优先级继承 

1.概念

上一个代码的问题在于,LPTask低优先级任务获得了锁,但是它优先级太低而无法运行。

如果能提升LPTask任务的优先级,让它能尽快运行、释放锁,"优先级反转"的问题不就解决了吗?

优先级继承:
        \bullet 假设持有互斥锁的是任务A,如果更高优先级的任务B也尝试获得这个锁
        \bullet 任务B说:你既然持有宝剑,又不给我,那就继承我的愿望吧
        ​​​​​​​\bullet 于是任务A就继承了任务B的优先级
        ​​​​​​​\bullet 这就叫:优先级继承
        ​​​​​​​\bullet 等任务A释放互斥锁时,它就恢复为原来的优先级
        \bullet 互斥锁内部就实现了优先级的提升、恢复

2.代码示例

基于上一个代码,我们只需要做一个简单的修改

int main( void )
{prvSetupHardware();/* 创建互斥量 *///xLock = xSemaphoreCreateBinary( );xLock = xSemaphoreCreateMutex();

创建一个互斥量即可,运行时序图如下图所示:

​​​​​​​\bullet A:HPTask执行 xSemaphoreTake(xLock, portMAX_DELAY); ,它的优先级被LPTask继承
​​​​​​​\bullet B:LPTask抢占MPTask,运行
​​​​​​​\bullet C:LPTask执行 xSemaphoreGive(xLock); ,它的优先级恢复为原来值
​​​​​​​\bullet D:HPTask得到互斥锁,开始运行
​​​​​​​\bullet 互斥锁的"优先级继承",可以减小"优先级反转"的影响 


五、递归锁

1.死锁的概念

在我之前的博客讲互斥锁的时候也讲过什么情况下会造成死锁,例如,线程 A 持有锁 L1 并请求锁 L2,而线程 B 持有锁 L2 并请求锁 L1,这种情况可能导致死锁。所以我们编写程序时要注意,不要写成死锁的情况,等以后写一些大型的代码,需要同时操控几个互斥量时,可能会犯这种错误。

假设有2个互斥量M1、M2,2个任务A、B:
        ​​​​​​​​​​​​​​\bullet A获得了互斥量M1
        ​​​​​​​​​​​​​​\bullet B获得了互斥量M2
        ​​​​​​​​​​​​​​\bullet A还要获得互斥量M2才能运行,结果A阻塞
        ​​​​​​​​​​​​​​\bullet B还要获得互斥量M1才能运行,结果B阻塞
        ​​​​​​​​​​​​​​\bullet A、B都阻塞,再无法释放它们持有的互斥量
        ​​​​​​​\bullet 死锁发生!

2.自我死锁

假设这样的场景:
        ​​​​​​​\bullet 任务A获得了互斥锁M
        ​​​​​​​​​​​​​​\bullet 它调用一个库函数
        ​​​​​​​​​​​​​​\bullet 库函数要去获取同一个互斥锁M,于是它阻塞:任务A休眠,等待任务A来释放互斥锁!
        ​​​​​​​​​​​​​​\bullet 死锁发生!
一个任务申请锁后调用其他函数时申请同一个锁,导致要释放锁的任务阻塞,从而无法释放锁。

3.函数

怎么解决这类问题?可以使用递归锁(Recursive Mutexes),它的特性如下:
        ​​​​​​​​​​​​​​\bullet 任务A获得递归锁M后,它还可以多次去获得这个锁
        ​​​​​​​​​​​​​​\bullet "take"了N次,要"give"N次,这个锁才会被释放

递归锁的函数一般互斥量的函数名不一样,参数类型一样,列表如下:

函数原型如下:

/* 创建一个递归锁,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void );/* 释放 */
BaseType_t xSemaphoreGiveRecursive( SemaphoreHandle_t xSemaphore );/* 获得 */
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait
);

注意:要使用递归锁,需要定义配置项configUSE_RECURSIVE_MUTEXES!!!

 4.递归锁代码示例

递归锁实现了:谁上锁就由谁解锁。

main函数里创建了2个任务
        ​​​​​​​​​​​​​​\bullet 任务1:高优先级,一开始就获得递归锁,然后故意等待很长时间,让任务2运行
        ​​​​​​​​​​​​​​\bullet 任务2:低优先级,看看能否操作别人持有的锁
main函数代码如下:

/* 递归锁句柄 */
SemaphoreHandle_t xMutex;
int main( void )
{prvSetupHardware();/* 创建递归锁 */xMutex = xSemaphoreCreateRecursiveMutex( );if( xMutex != NULL ){/* 创建2个任务: 一个上锁, 另一个自己监守自盗(看看能否开别人的锁自己用)*/xTaskCreate( vTakeTask, "Task1", 1000, NULL, 2, NULL );xTaskCreate( vGiveAndTakeTask, "Task2", 1000, NULL, 1, NULL );/* 启动调度器 */vTaskStartScheduler();}else{/* 无法创建递归锁 */}/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */return 0;
}

两个任务经过精细设计,代码和运行流程如下图所示:
        ​​​​​​​​​​​​​​\bullet A:任务1优先级最高,先运行,获得递归锁
        ​​​​​​​​​​​​​​\bullet B:任务1阻塞,让任务2得以运行
        ​​​​​​​​​​​​​​\bullet C:任务2运行,看看能否获得别人持有的递归锁:不能
        ​​​​​​​​​​​​​​\bullet D:任务2故意执行"give"操作,看看能否释放别人持有的递归锁:不能
        ​​​​​​​​​​​​​​\bullet E:任务2等待递归锁
        ​​​​​​​​​​​​​​\bullet F:任务1阻塞时间到后继续运行,使用循环多次获得、释放递归锁
        ​​​​​​​​​​​​​​\bullet 递归锁在代码上实现了:谁持有递归锁,必须由谁释放

程序运行结果如下图所示:

http://www.dinnco.com/news/19805.html

相关文章:

  • 百度 模块网站百度问答平台入口
  • 网站开发分销系统太原seo团队
  • 做销售在哪个网站找客户端windows优化大师的特点
  • 无锡网站建设价格低广州做网站的公司哪家好
  • 网站安全检测腾讯竞价托管公司
  • 如何在百度里建网站拼多多关键词排名查询工具
  • 网站建设案例价位厦门网络关键词排名
  • 技术支持 东莞网站建设网络营销好不好
  • 邱县专业做网站经典广告
  • 建设银行郑州市自贸区分行网站西安自动seo
  • 免费商城网站系统营业推广
  • 党建网站 自身建设如何建立网站平台的步骤
  • 有关政府网站模板营业推广怎么写
  • 网站建设与运营市场开拓方案seo网站优化建议
  • 建一个商城网站需要多久软文模板app
  • 广州排名网站关键词优化搜索引擎网址
  • 深圳购物商城网站建设深圳网站seo
  • 网站开发必学的技巧有哪些深圳网站建设微信开发
  • 优秀的电商设计网站有哪些内容百度seo多少钱一个月
  • 做教育培训网站鸣蝉智能建站
  • 公司品牌flash网站设计baidu 百度一下
  • 中天建设集团有限公司董事长武汉百度快照优化排名
  • 一个网站建设的组成百度站长统计工具
  • 网站建设 图片seo翻译
  • 哪个网站做外贸假发好新发布的新闻
  • 卡片式设计 网站成都网络推广
  • wordpress 会员插件采集站seo赚钱辅导班
  • 设计一套企业网站设计报价东莞关键词排名seo
  • 给企业做免费的推广seo排名首页
  • 用wex5可以做网站吗网站设计公司怎么样