【问题标题】:How can I see which CPU core a thread is running in?如何查看线程在哪个 CPU 内核中运行?
【发布时间】:2011-12-23 08:38:25
【问题描述】:

在Linux中,假设一个线程的pid是[pid],从目录/proc/[pid]我们可以得到很多有用的信息。例如,这些 proc 文件 /proc/[pid]/status、/proc/[pid]/stat 和 /proc/[pid]/schedstat 都很有用。但是我怎样才能得到一个线程正在运行的 CPU 核心数呢?如果一个线程处于睡眠状态,我怎么知道它再次调度后会运行哪个内核?

顺便说一句,有没有办法为每个 CPU 核心转储运行和睡眠任务的进程(线程)列表?

【问题讨论】:

  • 考虑转移到 superuser.com - 在那里获得答案的机会更大。
  • @ringbearer,这也可能是一个 Linux 编程问题。
  • 如果您是因为想在 C 中执行此操作而来到这里,则可以使用 sched_getcpu() 获取调用者的 CPU。

标签: linux linux-kernel scheduled-tasks scheduling scheduler


【解决方案1】:
To see the threads of a process :

ps -T -p PID

To see the thread run info

ps -mo pid,tid,%cpu,psr -p PID

Example :

/tmp # ps -T -p 3725
  PID  SPID TTY          TIME CMD
 3725  3725 ?        00:00:00 Apps
 3725  3732 ?        00:00:10 t9xz1d920
 3725  3738 ?        00:00:00 XTimer
 3725  3739 ?        00:00:05 Japps
 3725  4017 ?        00:00:00 QTask
 3725  4024 ?        00:00:00 Kapps
 3725  4025 ?        00:00:17 PTimer
 3725  4026 ?        00:01:17 PTask
 3725  4027 ?        00:00:00 RTask
 3725  4028 ?        00:00:00 Recv
 3725  4029 ?        00:00:00 QTimer
 3725  4033 ?        00:00:01 STask
 3725  4034 ?        00:00:02 XTask
 3725  4035 ?        00:00:01 QTimer
 3725  4036 ?        00:00:00 RTimer
 3725  4145 ?        00:00:00 t9xz1d920
 3725  4147 ?        00:00:02 t9xz1d920
 3725  4148 ?        00:00:00 t9xz1d920
 3725  4149 ?        00:00:00 t9xz1d920
 3725  4150 ?        00:00:00 t9xz1d920
 3725  4865 ?        00:00:02 STimer

/tmp #
/tmp #
/tmp # ps -mo pid,tid,%cpu,psr -p 3725
  PID   TID %CPU PSR
 3725     -  1.1   -
    -  3725  0.0   2
    -  3732  0.1   0
    -  3738  0.0   0
    -  3739  0.0   0
    -  4017  0.0   6
    -  4024  0.0   3
    -  4025  0.1   0
    -  4026  0.7   0
    -  4027  0.0   3
    -  4028  0.0   7
    -  4029  0.0   0
    -  4033  0.0   4
    -  4034  0.0   1
    -  4035  0.0   0
    -  4036  0.0   2
    -  4145  0.0   2
    -  4147  0.0   0
    -  4148  0.0   5
    -  4149  0.0   2
    -  4150  0.0   7
    -  4865  0.0   0
/tmp #

【讨论】:

    【解决方案2】:

    接受的答案不准确。以下是在查询时找出哪个 CPU 正在运行线程(或者是最后一个运行的线程)的方法:

    1. 直接阅读/proc/<pid>/task/<tid>/stat。在这样做之前,请确保格式没有随着最新内核而改变。文档并不总是最新的,但至少您可以尝试https://www.kernel.org/doc/Documentation/filesystems/proc.txt。在撰写本文时,它将是最后的第 14 个值。
    2. 使用ps。要么给它-F 开关,要么使用输出修饰符并添加代码PSR
    3. 将顶部与 Last Used Cpu 列一起使用(点击 f 可让您选择列)
    4. 将 htop 与 PROCESSOR 列一起使用(点击 F2 即可进入设置屏幕)

    【讨论】:

      【解决方案3】:

      自 2014 年起,以下答案不再准确

      任务不会在任何特定核心中休眠。而且调度程序不会提前知道它将在哪个内核上运行线程,因为这将取决于这些内核的未来使用情况。

      要获得所需的信息,请查看 /proc//task//status。如果线程正在运行,第三个字段将是“R”。最后一个字段的第六个将是线程当前正在运行的核心,或者如果当前未运行,则它最后运行(或迁移到)的核心。

      31466(BC)的取值强> 31348 31466 31348 34819 31466 4202496 2557 0 0 0 5006 16 0 0 20 0 1 0 10196934 121827328 1091 18446744073709551615 4194304 4271839 140737264235072 140737264232056 217976807456 0 0 0 137912326 18446744071581662243 0 0 17 3 0 0 0 0 0

      当前未运行。最后在核心 3 上运行。

      31466(BC)的 - [R 强> 31348 31466 31348 34819 31466 4202496 2557 0 0 0 3818 12 0 0 20 0 1 0 10196934 121827328 1091 18446744073709551615 4194304 4271839 140737264235072 140737264231824 4235516 0 0 0 2 0 0 0 17 2 0 0 0 0 0

      目前在核心 2 上运行。

      要了解其余字段的含义,请查看 Linux 内核源代码——特别是 fs/proc/array.cDocumentation/filesystems/stat.txt 中的 do_task_stat 函数。

      请注意,所有这些信息在您获得时可能已经过时。在您对 proc 中的文件进行 open 调用和该调用返回之间的某个时间点确实如此。

      【讨论】:

      • 感谢您的快速回复。我还有一个问题:stackoverflow.com/questions/7849353/…。如果我将线程固定到专用核心,那么一切都很好。这就是为什么我想知道这个问题的答案。
      • 此答案发布于 2011 年。2014 年,此 status 文件不再使用此格式,请参阅其他答案
      【解决方案4】:

      这可以通过 top 命令完成。默认的top 命令输出不显示这些详细信息。要查看此详细信息,您必须在顶部命令界面按 f 键,然后按 j(按按下 j 后的 Enter 键)。现在,输出将显示有关进程及其运行的处理器的详细信息。示例输出如下所示。

      top - 04:24:03 up 96 days, 13:41,  1 user,  load average: 0.11, 0.14, 0.15
      Tasks: 173 total,   1 running, 172 sleeping,   0 stopped,   0 zombie
      Cpu(s):  7.1%us,  0.2%sy,  0.0%ni, 88.4%id,  0.1%wa,  0.0%hi,  0.0%si,  4.2%st
      Mem:   1011048k total,   950984k used,    60064k free,     9320k buffers
      Swap:   524284k total,   113160k used,   411124k free,    96420k cached
      
        PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  P COMMAND
      12426 nginx     20   0  345m  47m  29m S 77.6  4.8  40:24.92 7 php-fpm
       6685 mysql     20   0 3633m  34m 2932 S  4.3  3.5  63:12.91 4 mysqld
      19014 root      20   0 15084 1188  856 R  1.3  0.1   0:01.20 4 top
          9 root      20   0     0    0    0 S  1.0  0.0 129:42.53 1 rcu_sched
       6349 memcache  20   0  355m  12m  224 S  0.3  1.2   9:34.82 6 memcached
          1 root      20   0 19404  212   36 S  0.0  0.0   0:20.64 3 init
          2 root      20   0     0    0    0 S  0.0  0.0   0:30.02 4 kthreadd
          3 root      20   0     0    0    0 S  0.0  0.0   0:12.45 0 ksoftirqd/0
      

      输出中的 P 列显示当前正在执行进程的处理器内核编号。对此进行几分钟的监控将使您了解 pid 在其间切换处理器内核。您还可以验证您设置了亲和力的 pid 是否仅在该特定核心上运行

      top f 导航屏幕 (实时系统示例):

      Fields Management for window 1:Def, whose current sort field is forest view
         Navigate with Up/Dn, Right selects for move then <Enter> or Left commits,
         'd' or <Space> toggles display, 's' sets sort.  Use 'q' or <Esc> to end!
      
      * PID     = Process Id
      * USER    = Effective User Name
      * PR      = Priority
      * NI      = Nice Value
      * VIRT    = Virtual Image (KiB)
      * RES     = Resident Size (KiB)
      * SHR     = Shared Memory (KiB)
      * S       = Process Status
      * %CPU    = CPU Usage
      * %MEM    = Memory Usage (RES)
      * TIME+   = CPU Time, hundredths
      * COMMAND = Command Name/Line
        PPID    = Parent Process pid
        UID     = Effective User Id
        RUID    = Real User Id
        RUSER   = Real User Name
        SUID    = Saved User Id
        SUSER   = Saved User Name
        GID     = Group Id
        GROUP   = Group Name
        PGRP    = Process Group Id
        TTY     = Controlling Tty
        TPGID   = Tty Process Grp Id
        SID     = Session Id
        nTH     = Number of Threads
      * P       = Last Used Cpu (SMP)
        TIME    = CPU Time
        SWAP    = Swapped Size (KiB)
        CODE    = Code Size (KiB)
        DATA    = Data+Stack (KiB)
        nMaj    = Major Page Faults
        nMin    = Minor Page Faults
        nDRT    = Dirty Pages Count
        WCHAN   = Sleeping in Function
        Flags   = Task Flags <sched.h>
        CGROUPS = Control Groups
        SUPGIDS = Supp Groups IDs
        SUPGRPS = Supp Groups Names
        TGID    = Thread Group Id
        ENVIRON = Environment vars
        vMj     = Major Faults delta
        vMn     = Minor Faults delta
        USED    = Res+Swap Size (KiB)
        nsIPC   = IPC namespace Inode
        nsMNT   = MNT namespace Inode
        nsNET   = NET namespace Inode
        nsPID   = PID namespace Inode
        nsUSER  = USER namespace Inode
        nsUTS   = UTS namespace Inode
      

      【讨论】:

        【解决方案5】:

        线程不需要绑定一个特定的核心(如果你没有固定它)。因此,要查看内核的连续切换,您可以使用(Dmitry 的修改答案):

        watch -tdn0.5 ps -mo pid,tid,%cpu,psr -p \`pgrep BINARY-NAME\`
        

        例如:

        watch -tdn0.5 ps -mo pid,tid,%cpu,psr -p \`pgrep firefox\`
        

        【讨论】:

          【解决方案6】:

          “top”命令可能对此有所帮助,它没有 CPU 分组的线程列表,但您可以查看线程列表(可能针对单个进程)以及线程运行在哪些 CPU 内核上

          top -H -p {PROC_ID}

          然后按f进入字段选择,j启用CPU核心列,回车显示。

          【讨论】:

            【解决方案7】:

            你也可以使用ps,像这样:

            ps -mo pid,tid,%cpu,psr -p `pgrep BINARY-NAME`
            

            【讨论】:

              猜你喜欢
              • 2016-08-28
              • 2017-08-22
              • 2013-02-27
              • 1970-01-01
              • 1970-01-01
              • 2014-02-02
              • 2016-05-08
              • 2016-08-16
              • 1970-01-01
              相关资源
              最近更新 更多