1

我正在使用 ChibiOS RTOS,我有一些看起来很基本的问题,但有点让我想不到。

ChibiOS 有一个函数叫做:

chSysLock();

chSysUnlock();

据我了解,这两个函数将分别锁定和解锁内核。

所以我的问题是:

  1. 锁定内核有什么作用?
  2. 为什么要锁定内核?

最后,让我们使用这个例子:

static void sem_cb(void) {
    chSysLock();
    chBSemSignalI(&sem_1);
    chSysUnlock();
}

这个函数只是为任何线程等待它的信号量发出信号。

所以我的最后一个问题是:

  1. 锁定内核只是为了发出信号量有什么意义?如果我不这样做,那么 ChibiOS 会抱怨并且在没有系统锁的情况下无法编译。
4

1 回答 1

1

通常,在 RTOS 内核锁定中,调度程序不会运行,因此不会发生上下文切换。通常也禁用一些或所有中断。锁定用于关键部分 - 必须在没有中断或抢占的情况下运行的代码部分。

我不是 ChibiOS 方面的专家,但它在这方面似乎有些过于复杂,并且没有非常全面的文档记录。这里描述了内核状态。它有两种锁定模式,并chSysLock()调用 S-Locked 状态,其中

"内核锁定并禁用常规中断源。启用快速中断源。在此状态下可调用 S-Class 和 I-Class API。 "

从文档中不清楚这是否意味着只能使用I/S 类 API,或者I/S-mode只能在锁定时调用 API。整个状态及其目的没有明确定义 IMO。然而,在某些 RTOS 中,具有不调用调度程序的特殊版本的函数是很常见的,这使常规 API 函数免于检查内核状态或中断上下文的开销,并且是一个小的优化(以牺牲安全性为代价)我的意见)。chBSemSignalI的文档证实了这一点:

笔记

此功能不会重新安排。

[...]

功能类:

这是一个 I-Class API,线程和中断处理程序都可以从系统锁定区域内调用此函数。

在您的示例中,发生的情况是给出了信号量,但调度程序不会运行,因此任何等待线程都不会立即准备就绪。目前尚不清楚是否chSysUnlock()会导致调度程序运行 - 文档说“特殊功能,此功能有特殊要求,请参阅注释。 ”,但没有提供有关这些注释在哪里可以找到的线索。

我希望调度程序能够运行,从表面上看,该功能sem_cb()似乎没有什么用处;但是我也希望chSysLock()/chSysUnlock()是可嵌套的,在这种情况下,函数的目的更有意义。sem_cb()无论内核状态如何,它都允许使用单个信号量函数 ( )。也就是说,在 normal 和 S-State 中调用都是安全的,但会增加单独的 S-State/Normal state API 旨在避免的开销。就我个人而言,至少在可以证明开销是不可接受的之前,我总是会寻求安全(尽管不一定以这种方式实现它)。它本质上说“_give 信号量,如果内核没有被锁定重新调度,否则推迟重新调度直到内核被解锁 - 即在最后一次嵌套解锁之后”。

但是它不允许sem_cb()从中断上下文中调用,因为这需要chSysLockFromISR().

以上从文档和“预期的”RTOS 行为中做出了很多假设。如果我碰巧在面对如此少的文档时使用 ChibOS,我会检查源代码以确定确切的行为。

于 2018-04-01T11:59:26.163 回答