FreeRTOS信号量
二值信号量
二值信号量既可以用于临界资源访问也可以用于同步功能 。互斥量有优先级继承机制, 二值信号量则没有这个机制。 所以二值信号量更偏向应用于同步功能(任务与任务间的同步或任务和中断间同步), 而互斥量更偏向应用于临界资源的访问 。
用作同步时,信号量在创建后应被置为空,任务A 获取信号量而进入阻塞,任务 B在某种条件发生后,释放信号量,于是任务 A 获得信号量得以进入就绪态,如果任务 A 的优先级是最高的,那么就会立即切换任务,从而达到了两个任务间的同步。
同样的,在中断服务函数中释放信号量, 任务 A 也会得到信号量,从而达到任务与中断间的同步。 即只有当对应中断发生时,CPU才去去执行某一任务,而这个任务处于阻塞状态。
创建二值信号量:
二值信号量句柄 = xSemaphoreCreateBinary()
获取二值信号量:
xSemaphoreTake(二值信号量句柄,等待时间)
给出二值信号量:
xSemaphoreGive( 二值信号量句柄); 任务中二值信号量释放?
在中断处理函数中释放信号量: 中断中二值信号量释放?
xSemaphoreGiveFromISR (…)
计数信号量
计数信号量肯定是用于计数的,在实际的使用中,我们常将计数信号量用于事件计数与资源管理。每当某个事件发生时,任务或者中断将释放一个信号量(信号量计数值加 1),当处理被事件时(一般在任务中处理),处理任务会取走该信号量(信号量计数值减 1),信号量的计数值则表示还有多少个事件没被处理。此外,系统还有很多资源,我们也可以使用计数信号量进行资源管理,信号量的计数值表示系统中可用的资源数目,任务必须先获取到信号量才能获取资源访问权,当信号量的计数值为零时表示系统没有可用的资源,但是要注意,在使用完资源的时候必须归还信号量,否则当计数值为 0的时候任务就无法访问该资源了。
在事件控制块中增加了计数器,这个计数器可以表示为事件发生的次数或者对资源数量的管理。计数信号量有释放信号量操作和获取信号量操作,释放信号量操作的时候计数器的值会加一,获取信号操作,计数器的值减一,如果减到0任务会进入到等待状态。
创建一个计数信号量:
计数信号量句柄 = xSemaphoreCreateCounting(5,5); //有5个信号量可用
获取一个计数信号量:
xSemaphoreTake(句柄,等待时间) //获取信号量,计数值减一
给出信号量:
xSemaphoreGive(句柄) //释放信号量,计数值加一
优先级翻转
共享资源,可以是一段程序、一个功能、一个动作、一段指令或者传输几个字节,也可以是不能同步运行的不相关的多段程序,不同的程序被封装成一个“外壳”,被认为是同一种共享资源S。
假设有A、B和C三个任务,优先级A>B>C,程序开始,A、B、C处于阻塞状态,任务C捕捉到信号量,开始执行任务C,任务C中使用了共享资源S,接着任务A捕捉到信号量,CPU使用权被任务A抢占,开始执行任务A,任务C被挂起,当运行到共享资源S的地方,发现其被任务C使用,任务A被挂起,任务C开始执行。这时候任务B捕捉到信号量,开始执行任务B,任务B结束以后,才开始执行任务C,任务C释放共享资源后,任务A才能执行。事实上,任务B的优先级低于任务A,但是任务A却要等待任务B,形成了优先级翻转。
优先级继承,是互斥信号量具有的机制,当一个互斥信号量正在被低优先级的任务使用,有个高优先级任务尝试获取互斥信号量时,会被阻塞。不过这个高优先级的任务会将低优先级任务的提升到与自己相同的优先级,这个过程就是优先级继承。
优先级继承 ,尽可能的降低了高优先级任务处于阻塞态的时间,并且将已经出现的“优先级翻转”的影响降到最低,但是只能减少影响,不能完全避免
互斥量
互斥量是一种特殊的二值信号量,它和信号量不同的是,它支持互斥量所有权、递归访问以及防止优先级翻转的特性,用于实现对临界资源的独占式处理。任意时刻互斥量的状态只有两种,开锁或闭锁。当互斥量被任务持有时,该互斥量处于闭锁状态,这个任务获得互斥量的所有权。当该任务释放这个互斥量时,该互斥量处于开锁状态, 任务失去该互斥量的所有权。当一个任务持有互斥量时,其他任务将不能再对该互斥量进行开锁或持有。 持有该互斥量的任务也能够再次获得这个锁而不被挂起,这就是递归访问,也就是递归互斥量的特性,这个特性与一般的信号量有很大的不同,在信号量中,由于已经不存在可用的信号量, 任务递归获取信号量时会发生主动挂起任务最终形成死锁 。
互斥量更多的是用于保护资源的互锁 。用于互锁的互斥量可以充当保护资源的令牌, 当一个任务希望访问某个资源时,它必须先获取令牌。当任务使用完资源后,必须还回令牌,以便其它任务可以访问该资源。
信号量会导致的另一个潜在问题,那就是任务优先级翻转 。而 FreeRTOS 提供的互斥量可以通过优先级继承算法, 可以降低优先级翻转问题产生的影响,所以,用于临界资源的保护一般建议使用互斥量 。
另外需要注意的是互斥量不能在中断服务函数中使用,因为其特有的优先级继承机制
只在任务起作用,在中断的上下文环境毫无意义。
创建互斥量:
句柄 = xSemaphoreCreateMutex()
获取互斥量:
xSemaphoreTake(句柄,等待时间)
释放互斥量:
xSemaphoreGive(句柄)
互斥量用于线程的互斥,信号线用于线程的同步。
互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。
- 全新的界面设计 ,将会带来全新的写作体验;
: mermaid语法说明
功能快捷键
撤销:Ctrl/Command + Z
我们支持6级标题。有助于使用TOC
语法后生成一个完美的目录。
如何改变文本的样式
强调文本 强调文本
加粗文本
加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block
var foo = 'bar';
生成一个适合你的列表
- 项目
- 项目
- 项目
- 项目
- 项目1
- 项目2
- 项目3
- 计划任务
- 完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' | ‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" | “Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash | – is en-dash, — is em-dash |
创建一个自定义列表
-
Markdown
- Text-to- HTML conversion tool Authors
- John
- Luke
如何创建一个注脚
一个具有注脚的文本。1
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
- 关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
注脚的解释 ↩︎