Operations 5 min read

How to Monitor Multi‑Threaded Linux Processes with top -H

This guide shows how to create and manage multiple pthreads in an embedded Linux program, then monitor each thread’s runtime using the top command with the -H option, including the need to set thread names via pthread_setname_np for clear identification.

Liangxu Linux
Liangxu Linux
Liangxu Linux
How to Monitor Multi‑Threaded Linux Processes with top -H

This example demonstrates how to create multiple POSIX threads, assign each a distinct name, and observe them with standard Linux monitoring tools.

Source file: multi_thread.c

#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// Maximum thread name length
#define APP_THREAD_NAME_MAX_LEN 32

typedef enum {
    APP_THREAD_INDEX_TEST0,
    APP_THREAD_INDEX_TEST1,
    APP_THREAD_INDEX_TEST2,
    APP_THREAD_INDEX_TEST3,
    APP_THREAD_INDEX_TEST4,
    APP_THREAD_INDEX_TEST5,
    APP_THREAD_INDEX_MAX
} app_thread_index_e;

typedef void *(*p_thread_fun)(void *param);

typedef struct {
    pthread_t thread_handle;
    p_thread_fun thread_entry;
    char name[APP_THREAD_NAME_MAX_LEN];
} app_thread_s;

static void *test0_thread_entry(void *param);
static void *test1_thread_entry(void *param);
static void *test2_thread_entry(void *param);
static void *test3_thread_entry(void *param);
static void *test4_thread_entry(void *param);
static void *test5_thread_entry(void *param);

app_thread_s s_app_thread_table[APP_THREAD_INDEX_MAX] = {
    {0, test0_thread_entry, "test0_thread"},
    {0, test1_thread_entry, "test1_thread"},
    {0, test2_thread_entry, "test2_thread"},
    {0, test3_thread_entry, "test3_thread"},
    {0, test4_thread_entry, "test4_thread"},
    {0, test5_thread_entry, "test5_thread"}
};

static void *test0_thread_entry(void *param) {
    printf("test0_thread running...
");
    while (1) { usleep(2 * 1000); }
    return NULL;
}
static void *test1_thread_entry(void *param) {
    printf("test1_thread running...
");
    while (1) { usleep(2 * 1000); }
    return NULL;
}
static void *test2_thread_entry(void *param) {
    printf("test2_thread running...
");
    while (1) { usleep(2 * 1000); }
    return NULL;
}
static void *test3_thread_entry(void *param) {
    printf("test3_thread running...
");
    while (1) { usleep(2 * 1000); }
    return NULL;
}
static void *test4_thread_entry(void *param) {
    printf("test4_thread running...
");
    while (1) { usleep(2 * 1000); }
    return NULL;
}
static void *test5_thread_entry(void *param) {
    printf("test5_thread running...
");
    while (1) { usleep(2 * 1000); }
    return NULL;
}

static int create_all_app_thread(void) {
    int ret = 0;
    for (int i = 0; i < APP_THREAD_INDEX_MAX; i++) {
        ret = pthread_create(&s_app_thread_table[i].thread_handle, NULL,
                             s_app_thread_table[i].thread_entry, NULL);
        if (ret != 0) {
            printf("%s thread create error! thread_id = %ld
",
                   s_app_thread_table[i].name, s_app_thread_table[i].thread_handle);
            return ret;
        }
        printf("%s thread create success! thread_id = %ld
",
               s_app_thread_table[i].name, s_app_thread_table[i].thread_handle);
        pthread_setname_np(s_app_thread_table[i].thread_handle,
                           s_app_thread_table[i].name);
        pthread_detach(s_app_thread_table[i].thread_handle);
    }
    return ret;
}

int main(int argc, char **argv) {
    create_all_app_thread();
    while (1) { usleep(2 * 1000); }
    return 0;
}

Compile the program with a POSIX‑thread aware compiler, for example: gcc -pthread multi_thread.c -o multi_thread Run the executable, then use the top utility to list each thread separately: top -H -p `pidof multi_thread` The -H flag tells top to display threads instead of just processes. The back‑ticks around pidof multi_thread are required to substitute the process ID at runtime.

Because each thread is named with pthread_setname_np, top shows the custom names (e.g., test0_thread , test1_thread , …). If the naming call is omitted, top will display the parent process name for every thread, making it impossible to distinguish them.

top output with thread names
top output with thread names
top output without thread names
top output without thread names

Thus, assigning names to threads via pthread_setname_np is essential for effective per‑thread monitoring on Linux.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Linuxmultithreadingpthreadtopthread monitoring
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.