How to Monitor Every Thread of an Embedded Linux Process with top -H
This guide shows how to create a multi‑threaded C program on embedded Linux, set thread names with pthread_setname_np, and use the top command with the -H option to display each thread’s status, illustrating the difference when thread names are omitted.
Example program
The source file multi_thread.c creates six POSIX threads, each of which runs an infinite loop that prints a status message and sleeps for 2 ms. Thread metadata (handle, entry function, and a human‑readable name) is stored in a static array. The program performs the following steps:
Define a maximum name length ( #define APP_THREAD_NAME_MAX_LEN 32) and an enumeration of thread indices.
Declare a function‑pointer type p_thread_fun for thread entry functions.
Define a structure app_thread_s containing pthread_t thread_handle, the entry function pointer, and a name buffer.
Implement six entry functions ( test0_thread_entry … test5_thread_entry) that print a message and then loop with usleep(2*1000).
Populate a global table s_app_thread_table with the thread descriptors and their names.
Provide create_all_app_thread() which iterates over the table, calls pthread_create() for each entry, checks the return value, prints success or error, sets the thread name with pthread_setname_np(), and detaches the thread.
In main() invoke create_all_app_thread() and keep the process alive with another infinite usleep loop.
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define APP_THREAD_NAME_MAX_LEN 32
typedef enum _app_thread_index {
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 _app_thread {
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) { 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; }
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 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;
}Observing thread activity with top
Compile the program (e.g., gcc -pthread multi_thread.c -o multi_thread) and run the resulting binary. While it is running, execute: top -H -p `pidof multi_thread` The -H option tells top to display each thread as a separate entry. The back‑ticks perform command substitution to obtain the PID of the running process.
If each thread calls pthread_setname_np() as shown, top -H will display the custom names ( test0_thread, …, test5_thread) in the COMMAND column, making it easy to identify individual thread activity. If the naming calls are omitted, top falls back to showing the process name for every thread.
This technique demonstrates how naming POSIX threads improves observability during debugging of multi‑threaded Linux applications using standard system tools.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
