根据 C 规范,中断是信号吗?
Is an interrupt a signal, according to the C spec?
C11 5.1.2.3/5:
When the processing of the abstract machine is interrupted by receipt
of a signal, the values of objects that are neither lock-free atomic
objects nor of type volatile sig_atomic_t are unspecified, as is the
state of the floating-point environment. The value of any object
modified by the handler that is neither a lock-free atomic object nor
of type volatile sig_atomic_t becomes indeterminate when the handler
exits, as does the state of the floating-point environment if it is
modified by the handler and not restored to its original state.
这个问题专门针对嵌入式系统,在没有类似操作系统的设置的情况下。
在嵌入式系统上,经典信号(POSIX 样式)不存在。假设我们有一个调用多个函数的中断,所有函数都在同一个((半)全局)变量上工作,但是这个变量不是在中断外上下文中使用的。像
static enum State state;
static void setStateTo1(void)
{
state = stateOne;
}
static void setStateTo2(void)
{
state = stateTwo;
}
void ISR(void)
{
if (state == stateOne)
setStateTo2();
else
setStateTo1();
}
两个问题:
- 中断是信号吗?
- 上面的代码是未定义行为的示例吗,因为
state
不是 volatile
?
术语 "signal" 指的是其行为由标准 (C11 7.14 "Signal handling") 定义的特定事物;该定义包括信号有一个数字,并且可以通过跳转到由 signal
函数安装的处理程序来中断执行,等等。
该标准不涵盖除信号和线程之外的任何其他类型的异步代码执行。
如果您的实现提供了不符合信号规范的任何其他类型的中断,并且中断处理程序更改了抽象机的行为,那么我们可以说该实现不符合要求,或者安装信号处理程序的代码会导致未定义的行为。
为了明确定义,您可以让处理程序除了编写 volatile 原子变量外什么都不做。
所以,你的第二个问题超出了标准的范围。在标准 C 中,如果程序从未调用过这些函数,优化器可以删除所有这些未使用的函数。
实际上,提供非标准中断的实现将在自己的范围内定义自己的行为,您可以将其视为具有附加功能的 C 的扩展方言。
标准的作者认为很多事情不在他们的管辖范围内。如果一个实现以一种方式使用堆栈,如果在程序执行期间发生任何中断,就会出现不可预测的故障,因此要求它生成的代码只能在不会发生中断的情况下为 运行,这样的限制不会使实施不符合要求,尽管它会使它不适用于许多目的。
旨在适合特定平台上的低级编程的高质量实现应该期望扩展 C 标准中给出的骨架抽象模型以包括平台抽象模型的任何部分,这些部分将是用于该目的,或者记录一个合理的理由,但实施质量问题不在标准的管辖范围之内。是否应该期望特定实现在超出标准预期的情况下有用取决于其设计者是否有兴趣使其适用于广泛的低级编程任务,或者只对适用于标准预期的目的感兴趣.
C11 5.1.2.3/5:
When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects that are neither lock-free atomic objects nor of type volatile sig_atomic_t are unspecified, as is the state of the floating-point environment. The value of any object modified by the handler that is neither a lock-free atomic object nor of type volatile sig_atomic_t becomes indeterminate when the handler exits, as does the state of the floating-point environment if it is modified by the handler and not restored to its original state.
这个问题专门针对嵌入式系统,在没有类似操作系统的设置的情况下。
在嵌入式系统上,经典信号(POSIX 样式)不存在。假设我们有一个调用多个函数的中断,所有函数都在同一个((半)全局)变量上工作,但是这个变量不是在中断外上下文中使用的。像
static enum State state;
static void setStateTo1(void)
{
state = stateOne;
}
static void setStateTo2(void)
{
state = stateTwo;
}
void ISR(void)
{
if (state == stateOne)
setStateTo2();
else
setStateTo1();
}
两个问题:
- 中断是信号吗?
- 上面的代码是未定义行为的示例吗,因为
state
不是volatile
?
术语 "signal" 指的是其行为由标准 (C11 7.14 "Signal handling") 定义的特定事物;该定义包括信号有一个数字,并且可以通过跳转到由 signal
函数安装的处理程序来中断执行,等等。
该标准不涵盖除信号和线程之外的任何其他类型的异步代码执行。
如果您的实现提供了不符合信号规范的任何其他类型的中断,并且中断处理程序更改了抽象机的行为,那么我们可以说该实现不符合要求,或者安装信号处理程序的代码会导致未定义的行为。
为了明确定义,您可以让处理程序除了编写 volatile 原子变量外什么都不做。
所以,你的第二个问题超出了标准的范围。在标准 C 中,如果程序从未调用过这些函数,优化器可以删除所有这些未使用的函数。
实际上,提供非标准中断的实现将在自己的范围内定义自己的行为,您可以将其视为具有附加功能的 C 的扩展方言。
标准的作者认为很多事情不在他们的管辖范围内。如果一个实现以一种方式使用堆栈,如果在程序执行期间发生任何中断,就会出现不可预测的故障,因此要求它生成的代码只能在不会发生中断的情况下为 运行,这样的限制不会使实施不符合要求,尽管它会使它不适用于许多目的。
旨在适合特定平台上的低级编程的高质量实现应该期望扩展 C 标准中给出的骨架抽象模型以包括平台抽象模型的任何部分,这些部分将是用于该目的,或者记录一个合理的理由,但实施质量问题不在标准的管辖范围之内。是否应该期望特定实现在超出标准预期的情况下有用取决于其设计者是否有兴趣使其适用于广泛的低级编程任务,或者只对适用于标准预期的目的感兴趣.