【问题标题】:Does each function and ISR get allocated its own stack size是否为每个函数和 ISR 分配了自己的堆栈大小
【发布时间】:2017-02-21 20:27:29
【问题描述】:

我假设这个问题取决于操作系统或平台。

它是在我使用端口音频库在 Windows 上编写 C++ 代码时出现的。

它在文档中声明不要在我的回调函数中编写太多将传递给端口音频引擎的代码,因为根据系统,它可以从 ISR 和另一个论坛上的阅读中调用,并指出它可能会导致堆栈溢出。

我不是在这里询问任何特定于端口音频的事情,但我想知道如果在 ISR 中编写的代码多于在主函数中编写的代码,为什么会出现堆栈空间问题。

我希望从回调中调用几个不同的函数。如果这个回调实际上是从 ISR 调用的,那么从 ISR 调用更多函数是否有问题?

当我调用每个函数时,由于每个函数都有自己的最大堆栈大小,这是否会为我提供额外的堆栈空间?我觉得这有点令人困惑。

我一直认为函数和 ISR 可以使用尽可能多的堆栈堆栈空间,直到完整分配的堆栈。这是否意味着主函数比其他函数拥有更大的堆栈部分。

非常感谢。

【问题讨论】:

  • 我冒昧地猜测一下,问题可能是在每个单独的回调结束之前您可能会获得很多 ISR,这意味着您将为所有这些 ISR 分配堆栈空间,这可能导致堆栈溢出

标签: c++ c function portaudio isr


【解决方案1】:

如果这个回调实际上是从 ISR 调用的,那么从 ISR 调用更多函数是否有问题?

可能是这样。 ISR 有多种风格,在许多情况下使用,并且一些组合为 ISR 提供​​了相当有限的堆栈空间。堆栈空间由(至少)ISR 自己的参数和局部变量以及它直接或间接调用的每个函数使用,函数调用有一些开销。该空间被重复用于顺序函数调用,但当一个函数调用另一个函数时,它是累积的。

当我调用每个函数时,由于每个函数都有自己的最大堆栈大小,这是否会为我提供额外的堆栈空间?

不,一般不会。 ISR 很可能会使用自己的堆栈空间来调用,与与其关联的任何程序的堆栈空间分开,但这是一种特殊情况。函数通常使用与其调用者相同的堆栈,但 ISR 没有传统意义上的 调用者。

我一直认为函数和 ISR 可以使用尽可能多的堆栈堆栈空间,直到完整分配的堆栈。这是否意味着主函数比其他函数拥有更大的堆栈部分[?]

ISR 可以根据需要使用提供给它的堆栈空间。该空间通常与关联程序的主堆栈分开,这对于在触发 ISR 时避免干扰主程序的状态很有用,并且在 ISR 是异步的时是必不可少的。分开时,ISR 的堆栈通常要小得多。

进程(主)堆栈的大小取决于系统,有时取决于可执行文件;它在main 和从main 直接或间接调用的所有函数之间共享。在单线程程序中,main 确实 可以访问比任何其他函数 f 更多的堆栈,但主要原因是 main 和(通常)调用链中的每个函数从mainf 占用了f 无法使用的堆栈空间。

【讨论】:

    【解决方案2】:

    老实说,我不会相信“另一个论坛”。

    文档没有说明使用过多的堆栈空间。它谈到了太多的代码,在 ISR 回调的上下文中,这意味着在 ISR 中花费了太多的时间

    ISR(包括回调)在中断被阻止的情况下执行。现在中断不会累积;控制器只能说中断是否处于挂起状态。如果 ISR 执行时间过长,则执行期间引发的中断将丢失。

    堆栈空间也可能是一个问题,但最重要的是,让您的回调速度更快。

    【讨论】:

    • 谢谢。 ISR 是否总是在中断被阻塞的情况下执行?
    【解决方案3】:

    我想知道如果 ISR 中编写的代码多于 main 函数中的代码,为什么会出现堆栈空间问题。

    堆栈空间可能不是 ISR 的主要关注点。 ISR 应该尽可能简单和快速,以最大限度地减少延迟,因此它不应该需要大堆栈。如果您必须进行任何重要的处理,您的 ISR 应该将任务排入队列以稍后在常规线程上运行以完成作业(有时称为上半部分和下半部分)。这可以通过条件变量、信号量或消息队列(仅举几例 IPC 机制)来实现。因此,如果 ISR 使用大量堆栈,则可能表明它在时间关键的调度周期内尝试执行过多的处理。

    此外,许多系统(例如 RTOS)要求您声明线程和 ISR 的堆栈大小。

    我希望从回调中调用几个不同的函数。如果这个回调实际上是从 ISR 调用的,那么从 ISR 调用更多函数是否有问题?

    只有在从 ISR 调用其他函数的情况下才应该如上所述最小化。您可以调用其他函数,但您应该尽可能推迟在 ISR 返回内核调度程序(以及未屏蔽的中断)之后运行 !)。

    另外 - 小心竞争条件!谨慎使用互斥锁对于保护共享状态是必要的。

    当我调用每个函数时,由于每个函数都有自己的最大堆栈大小,这是否会为我提供额外的堆栈空间?我觉得这有点令人困惑。

    否 - 函数没有自己的堆栈大小 - 线程有。对于 ISR,它取决于操作系统。调用每个函数会消耗更多的堆栈空间(基于调用嵌套级别)。

    我一直认为函数和 ISR 可以使用尽可能多的堆栈堆栈空间,直到完整分配的堆栈。

    是的,但是堆栈是每个线程的,而不是像堆那样的每个进程的。使用大量堆栈空间可能是设计问题的标志:在堆栈而不是堆上分配大对象、嵌套函数调用过多等。

    这是否意味着主函数比其他函数拥有更大的堆栈部分。

    不,因为堆栈是每个线程main 函数将位于应用程序调用堆栈的底部,但它可能会消耗少量或大量堆栈,这仅取决于其局部变量。

    一些不错的阅读:

    【讨论】:

    • 谢谢。对于只有一个线程且没有操作系统的微控制器,是什么决定了每个 ISR 的堆栈大小?
    • 简单地说 - 可用 RAM,减去程序文本(静态数据)和数据(应用程序二进制)段,以及堆。它确实取决于语言和编译器,但通常堆从底部增长而堆栈向下增长。本文有图好:quora.com/…
    【解决方案4】:

    它是在我使用端口音频库在 Windows 上编写 C++ 代码时出现的。

    请在 ISR 中尽可能少做,并让 DPC 排队以调用您的所有函数。甚至 DPC 也受到或应该受到资源限制,因此请考虑工作线程为 DPC 提供服务的设计。无论您做什么,都不要考虑在 ISR 中获取任何互斥锁。采收率。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-11
      • 2015-04-28
      • 2021-03-15
      • 2018-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-09
      相关资源
      最近更新 更多