Listing threads

Since the introduction of the Native POSIX Threads Library (NPTL) threads have become rather elusive. They don't show up in the default process listing using the ps command and if you are using the ps applet from Busybox they don't show up ever. In this note I will show how to display thread information using the full ps program and how to do the same thing in a shell script if you don't have it.

First, if you do have the luxury of the full ps command (from the procps package) on your target system then all you need to do is add the ā€œ-Lā€ option. For example to list all processes (-A) and all their threads (-L)

	ps -AL

Adding -f (full) gives more information:

	ps -ALf

More interesting, you can create custom output formats using the -o switch followed by a list of keywords. There are over 40 possibilities - read the ps man page for a complete list - among them

  • pid - the process ID
  • tid - the thread ID
  • class - the scheduling class, one of TS (SCHED_OTHER), FF ( SCHED_FIFO) or RR (SCHED_RR)
  • rtprio - priority of real-time tasks (1..99)
  • stat - state, one of R (running) S (sleeping) D (disk wait) T (stopped) Z (zombie)
  • comm - the command name
  • wchan - name of the kernel function in which the process is sleeping

For example

# ps -Leo pid,tid,class,rtprio,stat,comm,wchan
    1     1 TS       - Ss   init            wait
  277   277 TS       - Ss   sh              wait
 1093  1093 TS       - Sl   thread-test     futex_wait
 1093  1094 TS       - Sl   thread-test     hrtimer_nanosleep
 1093  1095 TS       - Sl   thread-test     hrtimer_nanosleep
 1093  1096 TS       - Sl   thread-test     hrtimer_nanosleep
 1149  1149 TS       - R+   ps              -

Note the four threads in process thread-test each have PID 1093 and have TIDs from 1093 to 1096.

Now, what if you only have the Busybox ps applet, or no ps at all? Of course, you could go and get procps and cross-compile the ps program or maybe find one already cross compiled. For the case where that is not possible or not worth the effort, here is a shell script I use that does almost the same as ps using just basic ash or bash syntax. It gathers information from the /proc file system (as the ps program does) and formats it in a fairly crude way. It is fairly easy to edit to change the information being displayed, as explained in the comments.


# A (b)ash script replacement for ps showing threads and other helpful stuff.
# Especially useful for Busybox based systems which has a very simple ps applet
# License: GPLv2
# Copyright 2009 Chris Simmonds, 2net Ltd

show_details ()
	# Read the stat entry for this process/thread. See man 5 proc for description
	     _RT_PRIORITY _POLICY _JUNK < /proc/$PID_TO_SHOW/stat

	# Decode policy and priority
	case $_POLICY in
		RTPRIO="- "
		RTPRIO="- "
	# _WCHAN is the address of the kernel function the task is blocked
	# in: not much use, so read /proc/NN/wchan to get the name of the function
	read _WCHAN < /proc/$PID_TO_SHOW/wchan

	# The output is more or less equivalent to "ps -Leo pid,tid,class,rtprio,stat,comm,wchan"
	echo -e "$PID\t$TID\t$POLICY\t$RTPRIO\t$_STATE\t$_COMM\t$_WCHAN"

	# Of course, you can easily change the line above to output more or less information
	# Here is an example which adds nice, vsize and rss
	# echo -e "$PID\t$TID\t$POLICY\t$RTPRIO\t$_NICE\t$_STATE\t$_VSIZE\t$_RSS\t$_COMM\t$_WCHAN"


# Print banner. If you change show_details() to output more (or different)
# information, change this as well so you know what is what

# Get a list of processes from /proc

# Doing it like this gives a numerical listing. The simpler "for p in /proc/[0-9]*"
# would give an alphabetic list in which 2 comes after 10 rather than before.
# N.B. Assumes PIDs are 5 digits or fewer (check /proc/sys/kernel/pid_max)
for p in /proc/[0-9] /proc/[0-9][0-9] /proc/[0-9][0-9][0-9] /proc/[0-9][0-9][0-9][0-9] /proc/[0-9][0-9][0-9][0-9][0-9]; do
	PID=$(basename $p)
	if [ -f /proc/$PID/stat ]; then

		# Look in /proc/NNNN/task for a list of threads
		for t in $p/task/*; do
			TID=$(basename $t)
			if [ $TID != $PID ]; then


1       1       TS      -       S       (init)  do_wait
277     277     TS      -       S       (sh)    do_wait
1093    1093    TS      -       S       (thread-test)   futex_wait
1093    1094    TS      -       S       (thread-test)   hrtimer_nanosleep
1093    1095    TS      -       S       (thread-test)   hrtimer_nanosleep
1093    1096    TS      -       S       (thread-test)   hrtimer_nanosleep
1098    1098    TS      -       R       (       0

Finally a note about 'C' libraries: NPTL was incorporated into the GNU C library 2.3 and requires a 2.6 kernel. Many embedded systems use the smaller uClibc library, which doesn't have NPTL, using the older Linux Threads library for POSIX threading. There is an on-going project to integrate NPTL into uClibc but it is not in general use yet. The main difference between NPTL and Linux Threads, so far as this discussion goes, is that in the former all threads have the PID of the process that contains them, whereas with Linux Threads each thread has its own PID. Thus threads show up in process listings by default if you are using Linux Threads but not with NPTL. However, my list_threads script is still useful (I believe) because it can show more information than Busybox.