在Linux中查找Thread的CPU使用情况

时间:2012-02-24 12:07:09

标签: c linux pthreads cpu-usage

我有一个在Linux上运行的基于C的应用程序,有大约30个线程。 现在我需要编写一个小实用程序,它在给定时间查找每个线程的CPU使用情况。它可以是应用程序的单独或部分。

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

请告诉我如何开始的一些想法。

由于

4 个答案:

答案 0 :(得分:1)

我建议给每个线程一个易于理解的名称。该名称在线程级“ ps”输出(因此为“ ps -L PID”)中可见。

您使用以下(不可移植的)pthread api为每个线程命名:

int pthread_setname_np(pthread_t thread, const char *name);

多线程雷鸟的示例输出:

 % 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

答案 1 :(得分:0)

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

1)维护一个更新的新PID列表,这些PID将在您的程序中在共享内存段中创建(我的想法是获取IPC的帮助)

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

答案 2 :(得分:0)

  

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

您可以使用pthread_setname_np设置线程名称来设置线程名称,并使用 / proc // task // status / proc //检查给定时间的线程名称task // stat ,然后在stackoverflow上检查以下答案calculating-cpu-usage-for-given-pid以获得一些想法!

答案 3 :(得分:0)

如OP所述,/proc文件系统为每个进程/proc/PROCESS-ID/stat和每个任务/proc/PROCESS-ID/task/TASKID/stat都有一个“ stat”文件。稍后是流程统计信息,它是所有任务(包括已完成的任务!)的汇总。

根据man procstat文件中的字段14、15包括使用的CPU(用户,内核)。

剩下的任务是将线程映射到TASKID。如手册页中所述(请参见引号),没有直接的API来获取gettid,而是需要syscall

对于交互式实用程序,请考虑使用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 ;
}

gettid的手册页指出:

  

GETTID(2)

     

NAME          gettid-获取线程标识

     

简介          #include

   pid_t gettid(void);

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

随后:   笔记          Glibc不为此系统调用提供包装器;使用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);
       ...
    }