c - 调试时,单线程应用程序会在内核之间跳转吗?

标签 c linux gdb eclipse-cdt u-boot

我正在尝试使用 Eclipse CDT 调试多架构 OSS 程序(沙箱配置下的 Das u-boot 引导加载程序 - 它生成标准的 linux 可执行文件)。我喜欢它呈现事物的方式(出色的 GUI 工作!)。例如,它为线程显示类似这样的内容,

Thread [1] 9480 [core:2] (Suspend:Step)

当我运行程序时,“核心编号”会发生变化(在 Intel i3 上运行时,值介于 0 和 3 之间)。这最初让我相信调试器向我展示了应用程序的不同处理上下文(即我认为它在所有 4 个处理器内核上运行)。我花了很多时间尝试安装“多核 gbd 调试器”并进行配置,但最后不得不承认失败。

当我在一个周末后回到这个问题时,我注意到虽然“核心编号”会改变,但线程 ID 不会(此外,我无法找到(在源代码中)fork 的位置()(或类似的)系统调用来自)。

我目前的理论是该程序确实作为单线程应用程序运行,但出于我不明白的原因,喜欢在我系统的不同处理器内核之间跳转。

我的问题如下;

  1. 我目前的理论是否正确?
  2. 如果是这样,对于在调试环境之外运行的__any__ 单线程应用程序,我是否可以期待这种行为?
  3. 从优化的角度来看,在核心之间移动时会有一定数量的上下文切换,即使对于单线程应用程序也是如此。跳来跳去有什么实际好处吗?

最佳答案

  1. 是的
  2. 是的
  3. 视情况而定。

发生的事情是,调度程序会根据许多变量为您的进程选择最佳 CPU(让我们将其定义为以下任意一种:物理 CPU、核心、超线程)来运行。通常,调度程序会尝试将进程保持在同一个 CPU 上,以避免 CPU 之间昂贵的缓存和 TLB 未命中,但它必须在将进程移动到它之前未在其上运行的 CPU 的成本和等待先前 CPU 可用的成本。

假设您的进程 X 在 CPU 0 上运行。它由于某种原因变得不可运行(等待锁定或 I/O 或抢占,因为它使用了太多 cpu 并且其他一些进程需要运行)。另一个进程 Y 开始在 CPU 0 上运行。由于某种原因,您的进程 X 再次变得可运行。 CPU 1 空闲。现在调度程序可以做出四种可能的决定:

  1. 等待进程 Y 完成运行,然后在 CPU 0 上运行进程 X。
  2. 抢占进程 Y,在 CPU 0 上运行进程 X,将进程 Y 移至 CPU 1。
  3. 抢占进程 Y,在 CPU 0 上运行进程 X,直到它停止运行,在 CPU 0 上恢复进程 Y。
  4. 在 CPU 1 上运行进程 X。

不同操作系统中的不同调度器会做出不同的决定。有些人喜欢所有进程的延迟较低,而忽略切换到不同 CPU 的成本,所以他们总是选择 4。有些人喜欢强亲和性,所以他们会选择 1。在许多情况下,调度程序会根据有根据的猜测来猜测有多少缓存状态进程 X 已离开 CPU 0 并决定由于该进程已挂起一段时间,它可能没有那么多缓存/TLB 留在 CPU 0 上,将它移动到一个不同的CPU。许多人会考虑内存总线布局并计算移动流程的成本,在您的情况下,调度程序可能知道进行移动很便宜。调度程序也可能会尽最大努力猜测进程 Y 的行为方式,如果它可能很快完成运行,它可能会等待它完成。等

一般来说,除非您正在做的事情确实需要从您的应用程序中挤出最后纳秒的性能,否则您不需要担心它。调度程序将做出足够好的决定,如果不是,那么对于大多数应用程序来说也没有那么重要。就您需要知道的而言,在大多数情况下,您的进程正在 CPU 之间移动,介于每条指令之间,从不移动。

关于c - 调试时,单线程应用程序会在内核之间跳转吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20608032/

相关文章:

c - 在 C 代码中循环输入并使用终端一次将数据写入不同的文件

c - 如何直接与硬件交互?

java - 用 Java 和 C 生成 CRC

linux - 运行数十小时后远程集群出现奇怪的 "Stale file handle, errno=116"

ios - 并行运行多个 lldb 进程

c++ - 使用 memcmp、memcpy 优化子例程

c - 在 linux 上,使用 ZLIB 的 compress() 和 uncompress() 函数,它有时会返回 Z_BUFFER_ERROR

linux - ubuntu安装后USB的再利用

multithreading - 将线程 ID 从顶部映射到 gdb

linux - QEMU-KVM 与 VMWare 使用 GDB 进行内核调试