我正在使用ChibiOS RTOS,我有一些看似基本的问题,但有点让我感到懊恼。
ChibiOS有一个名为:
的功能chSysLock();
和
chSysUnlock();
我的理解是这两个函数将分别锁定和解锁内核。
所以我的问题是:
最后,让我们使用这个例子:
static void sem_cb(void) {
chSysLock();
chBSemSignalI(&sem_1);
chSysUnlock();
}
此函数仅用信号通知线程正在等待它的信号量。
所以我的最后一个问题是:
答案 0 :(得分:1)
通常在RTOS内核锁定中,调度程序不会运行,因此不会发生上下文切换。通常也会禁用部分或全部中断。锁定用于关键部分 - 必须在不中断或抢占的情况下运行的代码段。
我不是ChibiOS的专家,但在这方面似乎有点过于复杂,并没有非常全面的记录。内核状态描述为here。它有两种锁定模式,chSysLock()
调用S-Locked状态,其中
“禁用内核锁定和常规中断源。启用快速中断源。在此状态下可以调用S-Class和I-Class API。”
从文档中不清楚这是否意味着可以使用仅 I / S-Class API,或者只能在锁定时调用I/S-mode
API。整个国家及其目的没有明确定义IMO。然而,在某些RTOS中,通常会有不调用调度程序的特殊版本的函数,这样可以节省常规API函数,从而不必检查内核状态或中断上下文,这是一个小的优化(以安全为代价)我的看法)。 chBSemSignalI的文档证实了这一点:
注意强>
此功能不会重新安排。
<强> [...] 强>
功能类:
这是一个I-Class API, 可以通过两者在系统锁定区域内调用此函数 线程和中断处理程序。
在您的示例中,正在发生的是信号量,但调度程序将不会运行,因此任何等待的线程都不会立即就绪。目前尚不清楚chSysUnlock()
是否导致调度程序运行 - 文档说“特殊功能,此功能有特殊要求请参阅注释。”,但不清楚这些注释可能在何处被发现。
我希望调度程序能够运行,从表面上看,函数sem_cb()
似乎没什么用处;但是我也希望chSysLock()/chSysUnlock()
可以嵌套,在这种情况下,函数的目的更有意义。它允许使用单个信号量给定函数(sem_cb()
),而不管内核状态如何。也就是说,在正常和S状态下调用是安全的,但增加了单独的S状态/正常状态API旨在避免的开销。就个人而言,我总是寻求安全(尽管不一定以这种方式实施)至少直到可以证明开销是不可接受的。它本质上说“_give信号量,如果内核没有锁定重新安排,否则推迟重新安排直到内核解锁 - 即在最后一次嵌套解锁之后”。
但是不允许从中断上下文中调用sem_cb()
,因为这需要chSysLockFromISR()
。
以上内容从文档和“预期的”RTOS行为中做出了很多假设。如果我碰巧在面对如此缺乏的文档时使用ChibOS,我会检查源代码以确定确切的行为。