You can examine the state of the process using proc file system. Each process running in the system will have an entry under /proc/pid
For a single-threaded process, you will find all the information about the state of the process under /proc/pid
The easiest way to find out if a given process is multi threaded or not is to examine the /proc/pid
One particular file that you will find very useful to understand the status of the threads (the only thread, in case of a single threaded application) is /proc/pid
Name: a.out
State: S (sleeping)
SleepAVG: 88%
Tgid: 15155
Pid: 15155
PPid: 1
TracerPid: 0
Uid: 9929 9929 9929 9929
Gid: 9929 9929 9929 9929
FDSize: 256
Groups: 10 9929
VmSize: 2792 kB
VmLck: 0 kB
VmRSS: 696 kB
VmData: 40 kB
VmStk: 504 kB
VmExe: 2 kB
VmLib: 2186 kB
StaBrk: 0804a000 kB
Brk: 096fe000 kB
StaStk: bff854b0 kB
ExecLim: ffffffff
Threads: 1
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 000000027f00000e
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
Let me explain each of the fields in this file.
Name: The name of the binary of this process.
State: The current state of the process. There are totally seven states of a process: running, sleeping, disk sleep, stopped, tracing stopped, zombie and dead. I will explain these states in a separate blog :-)
SleepAVG: I think this is average sleep time. I am not sure.
Tgid: Thread group ID. This is a single value, which implies that a thread cannot be a part of more than one thread group.
Pid: Process ID.
PPid: Parent process ID.
TracerPid: If the process is currently being traced, for e.g. using strace, this will contain the tracer's PID.
Uid: real user ID, effective user ID, saved user ID and the file system user ID.
Gid: real group ID, effective group ID, saved group ID and the file system group ID.
FDSize: What is the size of the file descriptor table for this process.
Groups: List of groups that the owner of the process belongs to. (I am not sure about this info).
VmSize: Total virtual memory size.
VmLck: Locked virtual memory size. (Refer to the man page for mmap and mlockall).
VmRSS: Resident set size. i.e. how much of the total virtual memory is resident in RAM.
VmData: How much of the virtual memory is data.
VmStk: How much of the virtual memory is stack.
VmExe: How much of the virtual memory is executable (a.k.a text).
VmLib: How much of the virtual memory shared object libraries occupy.
StaBrk: The starting address of the data that could be grown using sbrk() call.
Brk: The top of the data that has been reached using sbrk() call.
StaStk: I am not sure about this value.
ExecLim: I am not sure about this value either :-(
Threads: The number of threads this process has.
SigPnd: Signals pending to be delivered to this thread.
ShdPnd: Shared pending signals. I am not sure how this value is used.
SigBlk: Signals that the thread explicitly blocked. These signals will be delivered when the thread unblocks the signal.
SigIgn: Signals that the thread decided to ignore. There is a difference between blocking a signal and ignoring a signal. Pickup APUE and read the chapter on signals.
SigCgt: Signals that the thread decided to catch, by installing a signal handler. This is done through sigaction() function.
CapInh, CapPrm, CapEff: All I know is these are related to capabilities and they stand for capability inheritable, capability permitted and capability effective. I don't have an understanding of what they are.
Okay. Hopefully that helps in understanding the status of a thread when you look at status file next time.
Happy hacking and have a good weekend.