在Linux中查找线程的CPU使用率

7

我有一个在Linux上运行的基于C语言的应用程序,大约有30个线程。

现在我需要编写一个小工具,在给定时间内查找每个线程的CPU使用情况。它可以是独立的或作为应用程序的一部分。

/proc的问题之一是找到哪个线程是什么。

请给我一些开始的思路。

谢谢


1
我认为你可以从这个问题中得到足够的提示:https://dev59.com/-XA75IYBdhLWcg3wGU-I - jupp0r
4个回答

3
我建议给每个线程一个可读的名称。该名称在线程级别的“ps”输出中可见(因此为“ps -L PID”)。
使用以下(非可移植)pthread API 为每个线程赋予名称:
int pthread_setname_np(pthread_t thread, const char *name);

针对多线程 Thunderbird 的示例输出:

 % ps -o pid,pcpu,comm,cmd -L 7111
  PID %CPU COMMAND         CMD
 7111  8.3 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 Gecko_IOThread  /usr/lib/thunderbird/thunderbird
 7111  0.0 Link Monitor    /usr/lib/thunderbird/thunderbird
 7111  0.0 Socket Thread   /usr/lib/thunderbird/thunderbird
 7111  0.0 JS Watchdog     /usr/lib/thunderbird/thunderbird
 7111  0.0 JS Helper       /usr/lib/thunderbird/thunderbird
 7111  0.1 JS Helper       /usr/lib/thunderbird/thunderbird
 7111  0.1 JS Helper       /usr/lib/thunderbird/thunderbird
 7111  0.1 JS Helper       /usr/lib/thunderbird/thunderbird
 7111  0.0 AudioIPC Callba /usr/lib/thunderbird/thunderbird
 7111  0.0 AudioIPC Server /usr/lib/thunderbird/thunderbird
 7111  0.0 BGReadURLs      /usr/lib/thunderbird/thunderbird
 7111  0.0 Hang Monitor    /usr/lib/thunderbird/thunderbird
 7111  0.0 gmain           /usr/lib/thunderbird/thunderbird
 7111  0.0 gdbus           /usr/lib/thunderbird/thunderbird
 7111  0.0 Cache2 I/O      /usr/lib/thunderbird/thunderbird
 7111  0.0 Cookie          /usr/lib/thunderbird/thunderbird
 7111  0.0 Timer           /usr/lib/thunderbird/thunderbird
 7111  0.0 GMPThread       /usr/lib/thunderbird/thunderbird
 7111  0.5 Softwar~cThread /usr/lib/thunderbird/thunderbird
 7111  0.0 Compositor      /usr/lib/thunderbird/thunderbird
 7111  0.0 VRListener      /usr/lib/thunderbird/thunderbird
 7111  0.0 ImgDecoder #1   /usr/lib/thunderbird/thunderbird
 7111  0.0 ImageIO         /usr/lib/thunderbird/thunderbird
 7111  0.0 IPDL Background /usr/lib/thunderbird/thunderbird
 7111  0.0 HTML5 Parser    /usr/lib/thunderbird/thunderbird
 7111  0.0 LoadRoots       /usr/lib/thunderbird/thunderbird
 7111  0.0 DataStorage     /usr/lib/thunderbird/thunderbird
 7111  0.0 DataStorage     /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #1   /usr/lib/thunderbird/thunderbird
 7111  0.0 StyleThread#0   /usr/lib/thunderbird/thunderbird
 7111  0.0 StyleThread#1   /usr/lib/thunderbird/thunderbird
 7111  0.0 StyleThread#2   /usr/lib/thunderbird/thunderbird
 7111  0.0 ImgDecoder #2   /usr/lib/thunderbird/thunderbird
 7111  0.0 dconf worker    /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #2   /usr/lib/thunderbird/thunderbird
 7111  0.0 SysProxySetting /usr/lib/thunderbird/thunderbird
 7111  0.0 ProxyResolution /usr/lib/thunderbird/thunderbird
 7111  0.0 DataStorage     /usr/lib/thunderbird/thunderbird
 7111  0.0 URL Classifier  /usr/lib/thunderbird/thunderbird
 7111  0.0 Classif~ Update /usr/lib/thunderbird/thunderbird
 7111  0.0 DNS Resolver #1 /usr/lib/thunderbird/thunderbird
 7111  0.0 DOM Worker      /usr/lib/thunderbird/thunderbird
 7111  0.0 ImageBr~geChild /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #3   /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #4   /usr/lib/thunderbird/thunderbird
 7111  0.0 DNS Resolver #2 /usr/lib/thunderbird/thunderbird
 7111  0.0 mozStorage #5   /usr/lib/thunderbird/thunderbird
 7111  0.0 ImgDecoder #3   /usr/lib/thunderbird/thunderbird
 7111  0.0 DNS Resolver #3 /usr/lib/thunderbird/thunderbird
 7111  0.0 localStorage DB /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird
 7111  0.0 thunderbird     /usr/lib/thunderbird/thunderbird

2
正如OP所指出的,/proc文件系统对于每个进程都有一个'stat'文件,即/proc/PROCESS-ID/stat,对于每个任务,还有/proc/PROCESS-ID/task/TASKID/stat。后者是所有任务(包括已完成的任务)的进程状态的汇总。

根据man proc:stat文件中的第14、15字段包括使用的CPU时间(用户和内核)。

这就需要将线程映射到TASKID。正如手册中所述(请参阅引用),没有直接的API来获取tid,而需要系统调用。

对于交互式实用程序,请考虑使用top(使用y进行任务模式)

对于可在应用程序内部使用的代码,请参见以下内容。

#define _GNU_SOURCE
#include <stdio.h>

#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>

pid_t get_task_id(void) ;
int get_task_cpu(pid_t tid) ;

int main(int argc, char *argv[])
{
    pthread_create(...) ;
}

void thread_proc(void *arg) {
    pid_t tid = get_task_id() ;

    // do something

    int cpu = get_task_cpu(tid) ;
    printf("TID=%d CPU=%d\n", tid, cpu) ;
}

pid_t get_task_id(void) {
    pid_t tid = syscall(SYS_gettid);
    return tid ;
}

int get_task_cpu(pid_t tid) {
    char fname[200] ;
    snprintf(fname, sizeof(fname), "/proc/self/task/%d/stat", (int) get_task_id()) ;
    FILE *fp = fopen(fname, "r") ;
    if ( !fp ) return -1 ;
    int ucpu = 0, scpu=0, tot_cpu = 0 ;
    if ( fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %d %d",
        &ucpu, &scpu) == 2 )
        tot_cpu = ucpu + scpu ;
    fclose(fp) ;
    return tot_cpu ;
}

< p> gettid 的 man 页明确说明:

GETTID(2)

NAME gettid - get thread identification

SYNOPSIS #include

   pid_t gettid(void);

   Note: There is no glibc wrapper for this system call; see NOTES.

And later on: NOTES Glibc does not provide a wrapper for this system call; call it using syscall(2).

   The thread ID returned by this call is not the same thing as a POSIX thread ID (i.e., the opaque value returned by pthread_self(3)).
在syscall的示例代码中:
   #define _GNU_SOURCE
   #include <unistd.h>
   #include <sys/syscall.h>
   #include <sys/types.h>
   #include <signal.h>

   int
   main(int argc, char *argv[])
   {
       pid_t tid;

       tid = syscall(SYS_gettid);
       ...
    }

感谢你提供这个详细的答案!(唯一有价值的) - theduke

0
/proc 的一个问题是找到哪个线程是什么。您可以使用 pthread_setname_np 设置线程名称,并使用 /proc/<MainPID>/task/<threadID>/status/proc/<MainPID>/task/<threadID>/stat 检查给定时间的线程名称,然后查看 stackoverflow 上的这些答案 calculating-cpu-usage-for-given-pid 以获得一些想法!

0

虽然我在这个领域很幼稚,但我认为以下方法可能有效

1)在共享内存段中维护一个更新的新PID列表(我的想法是寻求IPC的帮助)

2)开发一个应用程序,能够访问先前创建的共享段并获取PID以检查相应的利用率。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接