1. Introduction
There are different ways to refer to processes executing in Linux, as every process has different identifiers from which we can retrieve information about the process.
In this tutorial, we will start with a conceptual definition of them. Next, we will move to different ways to retrieve the identifiers from other known information. We will describe what the output means and what equal or different values for the identifiers imply.
2. Background Information
First, let’s go through some basic parallel computing terminology. We need this knowledge to understand some concepts we’ll see later.
A process is a group of resources allocated for a given purpose, including memory space and file descriptors.
A thread is the simplest scheduling unit handled by a scheduler. In other words, a thread is the smallest set of instructions that a processor manipulates.
Parallel programming includes techniques to perform multiple operations simultaneously, achieving higher performance. The two common ways are multithreading and multiprocessing. The choice depends on factors such as computational resources or software architecture.
Multithreading relies on scheduling different tasks in multiple threads within the same process. This makes threads of the same process share the allocated memory resources of the system.
Multiprocessing consists of creating child processes from one parent process.
The communication between the resources of processes is not as straightforward as with threads, requiring an explicit declaration.
3. Definition and Differences
Let’s now see the definition of each identifier.
3.1. PID (Process Identifier)
It is a unique number that identifies every process running in the kernel. It starts at 1, which is assigned to systemd (or init on older Linux distributions).
3.2. TID (Thread Identifier)
It is an integer that serves to identify threads.
In serial programming, the TID and the PID are the same, as there is only one thread.
In multi-threaded environments, each thread has its own TID. All the threads from the same process have the same PID.
The TID is always equivalent to the LWP (LightWeight Process). The former is used in system interface functions, while the latter is used more often on the user side.
The number of threads within a process is the NLWP, which stands for the Number of LWP.
3.3. PPID (Parent Process Identifier)
When any program triggers a multiprocessing sequence, there is a parent process from which many child processes are created. The child processes have a different PID than the parent process PID.
However, all the child processes have the same PPID, which equals the PID of the parent process, denoting from which parent process they came.
4. Get PID From a Known Process Name
We can use the command pidof followed by the name of the process:
$ pidof firefox
19119 15535 15482 15182 15180 15040 14845 14751 14715 14666
The output lists all the PIDs with the specified process name.
Alternatively, there is a tool called pgrep that provides advanced functionalities to retrieve PID information from the application name.
To retrieve the PID of all the current system processes, commands like top are helpful.
5. Get All TID From a Known PID
Once we know the PID from a given process, we can retrieve the TID of all the threads that are running under the PID.
There are two ways to access this information. In Linux, everything is a file. In the root directory, there is a directory called /proc/ that contains one entry for each currently running process. Inside it, there is another directory, task/, that has one directory for each thread in the process.
Let’s take a PID from the previous example (14715) to get all its TIDs:
$ ls /proc/14715/task
14715 14719 14720 14723 21345
The output shows all the TIDs grouped under the PID 14715.
Based on the call to pidof in the previous section, we can see that Firefox is running in multiple threads. For the first thread, the PID and TID always match. The TID will always be equal to or larger than the PID.
Another way to retrieve the same information is with the ps command. The command has to be called for the desired PID with the –pid flag, the -L flag (to get the LWP identifiers), and with the flag -O followed by the desired output columns:
$ ps --pid 14715 -O tid,lwp,nlwp -L
PID TID LWP NLWP S TTY TIME COMMAND
14715 14715 14715 5 S ? 00:00:00 /usr/lib/firefox/firefox
14715 14719 14719 5 S ? 00:00:00 /usr/lib/firefox/firefox
14715 14720 14720 5 S ? 00:00:00 /usr/lib/firefox/firefox
14715 14723 14723 5 S ? 00:00:00 /usr/lib/firefox/firefox
14715 21345 21345 5 S ? 00:00:00 /usr/lib/firefox/firefox
Apart from the same TID retrieved before, the total count of process threads is obtained under the NLWP column. The output also shows that TID and LWP are the same.
6. Get PID From a Known TID
Another common query is to retrieve the PID from a known TID. To do so, there are two methods that rely on the same commands as before.
By exploring the /proc directory with the absolute directory tool readlink, we can retrieve the PID of a given TID.
For the TID 14719, this looks like this:
$ readlink -f /proc/*/task/14719 | cut -d/ -f3
14715
Here, the cut command in the pipeline splits the output of readlink (the full path of the TID) and returns the element before the third slash (which is the PID).
We can also use the ps combined with awk to retrieve the same information.
We can use similar flags (-L and -O) as before, combined with -e to return everything:
$ ps -e -O tid -L | awk '$2 == 14719'
14715 14719 S ? 00:00:00 /usr/lib/firefox/firefox
Here, we pipe the ps command output to awk, which finds and returns the line where the second column ($2) equals the TID we are searching for.
7. Get PPID From a Known PID
For multiprocessing, there are also two methods to obtain the PPID from a PID.
Within the /proc/ directory of the PID of interest, the file status contains information about the process. Searching (with the grep command) for PPid, we can get the PPID of the PID process.
In the case of the earlier process with PID 14715, the PPID is:
$ cat /proc/14715/status | grep PPid
PPid: 14666
We should note that the capitalization of the search term PPid is important to find the correct line in the status file.
We can also retrieve the PPID by specifying the PID with the –pid flag in the ps command and requesting the PPID column as output (with the -O ppid flag):
$ ps --pid 14715 -O ppid
PID PPID S TTY TIME COMMAND
14715 14666 S ? 00:00:00 /usr/lib/firefox/firefox
8. Get All PID From a Known PPID
Finally, to get the PID from a PPID, we propose only one solution because the “directories” approach is not as straightforward.
With the ps command, we can get the PID by specifying a PPID with the flag –ppid (the flag -O ppid only indicates that all should have the same PPID):
$ ps --ppid 14666 -O ppid
PID PPID S TTY TIME COMMAND
14715 14666 S ? 00:00:00 /usr/lib/firefox/firefox
14751 14666 S ? 00:00:22 /usr/lib/firefox/firefox
14845 14666 S ? 00:04:59 /usr/lib/firefox/firefox
15040 14666 S ? 00:42:41 /usr/lib/firefox/firefox
15180 14666 S ? 00:08:20 /usr/lib/firefox/firefox
15182 14666 S ? 00:01:07 /usr/lib/firefox/firefox
15482 14666 R ? 00:15:37 /usr/lib/firefox/firefox
15535 14666 S ? 00:06:21 /usr/lib/firefox/firefox
19119 14666 R ? 00:01:27 /usr/lib/firefox/firefox
From the results, we can say that firefox uses multiple processes and multiple threads. The process with PID 14666 spawns these different processes. Thus, the PPID from these processes (14715, 14751, 14845,…) is 14666.
The PIDs from child processes created from a parent process is larger than the PPID. For example, the process with PID 14666 cannot have a PPID of 14666 (as we can see in the last command output). This is because the process with PID 14666 is the parent process of firefox. Given that the system spawned this process, its PPID is the system PID.
9. Conclusion
In this article, we have discussed the differences between PID, TID, and PPID. With an applied example, we have discussed various commands to retrieve them from known information and what the output of these commands means.