Understanding Linux process management can be useful for both developers and system administrators. The ps command is an excellent way to get information about processes running on the system.
What is a process?
A process is a series of tasks executed by the operating system. In most cases the tasks are defined in a computer program (a set of instructions). The result of the execution of these programs are processes. Since Linux is a multiprocessing operating system, processes can be run concurrently and independently from each other. Each process has its own permissions, virtual memory address space, and so on.
A process can access and use system resources such as memory, CPUs, files on the file system, and physical devices. To manage and control access to these resources, the kernel needs to keep track of which processes are running and which resources are in use. The kernel does this using a data structure to represent the processes. This data structure is quite large and complex, so this article only focuses on a few categories of information.
Each process can be in one of the following states: RUNNING, WAITING, STOPPED or ZOMBIE. RUNNING and STOPPED are relatively straightforward to understand. The WAITING state means the process is waiting for an event or to access a resource , such as waiting for keyboard input. The ZOMBIE state describes a process which for some reason is stopped but still present in the list of processes managed by the kernel.
Each process in the system has a process identifier, or PID. Process also have user and group identifiers used to control access on the system resources.
Each process except for the initial one has a parent process. The kernel keeps track of the hierarchical relationship between processes.
This category is used to track access to any files a process has opened.
This category is used by the kernel to track the mapping of each process’ virtual memory onto the system’s physical memory. A process’ virtual memory is a virtual address space that contains executable code and the data from different sources. For example, when a program uses a shared library, the code and data from the library is linked to this process’ virtual memory. Another example is for a program to allocate virtual memory during processing, such as to hold the content of files that it is reading.
ps in action
Now that you have a better idea of what a process is, here’s a look at the ps command and how to use it to get information about our system’s running processes. To quickly print all the active processes, use the following command:
$ ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 20:31 ? 00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 24 root 2 0 0 20:31 ? 00:00:00 [kthreadd] root 4 2 0 20:31 ? 00:00:00 [kworker/0:0H] ....
Note the use of the -e option to display all processes, and -f to display the full format. You can also use -F for extended full format. The full format prints these eight columns:
- UID = user identifier
- PID = process identifier
- PPID = parent process identifier
- C = CPU utilization
- STIME = time when the process started
- TTY = terminal
- TIME = combined system and user CPU time used by the process so far
- CMD = process name including command
You can also see that systemd, which is the initial process, has a parent PID of 0. As the initial process, it has no parent.
The extended full format adds three more columns to the displayed output:
$ ps -eF UID PID PPID C SZ RSS PSR STIME TTY TIME CMD root 1 0 0 57658 11988 3 20:31 ? 00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 24 root 2 0 0 0 0 0 20:31 ? 00:00:00 [kthreadd] root 4 2 0 0 0 0 20:31 ? 00:00:00 [kworker/0:0H] root 6 2 0 0 0 0 20:31 ? 00:00:00 [mm_percpu_wq]
The new columns are:
- SZ = virtual memory usage
- RSS = real memory usage (resident set size)
- PSR = processor to which the process is currently assigned
You can also customize the output of the ps command. Use the -o option to specify which columns you would like to be displayed. This can be useful when using ps in a shell script.
$ ps -ef -o pid,cmd PID CMD 1 /usr/lib/systemd/systemd --switched-root --system --deserialize 24 2 [kthreadd] 4 [kworker/0:0H]
Another useful option is -u, which allows you to filter the processes displayed by user ID. For example, to display all the processes owned by the user root, run a command like this:
$ ps -u root -o user,pid,cpu,cmd USER PID CPU CMD root 1 - /usr/lib/systemd/systemd --switched-root --system --deserialize 24 root 2 - [kthreadd] root 4 - [kworker/0:0H] root 6 - [mm_percpu_wq] root 7 - [ksoftirqd/0]
Another example to print the processes owned by the gdm user.
$ ps -u gdm -o user,pid,cpu,cmd USER PID CPU CMD gdm 1126 - /usr/lib/systemd/systemd --user gdm 1139 - (sd-pam) gdm 1157 - /usr/libexec/gdm-wayland-session gnome-session --autostart /usr/share/gdm/greeter/autostart gdm 1180 - /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only gdm 1194 - /usr/libexec/gnome-session-binary --autostart /usr/share/gdm/greeter/autostart
Debugging using ps
The ps command comes in handy when debugging an application. More specifically, you can use it to determine the resources used by an application. To list all the threads for a particular process, run a command like this:
$ ps -C firefox -L -o pid,tid,pcpu,state,nlwp,cmd PID TID %CPU S NLWP COMMAND 3015 3015 7.6 S 69 /usr/lib64/firefox/firefox 3015 3040 0.0 S 69 /usr/lib64/firefox/firefox 3015 3041 0.0 S 69 /usr/lib64/firefox/firefox 3015 3042 0.5 S 69 /usr/lib64/firefox/firefox 3015 3043 0.3 S 69 /usr/lib64/firefox/firefox 3015 3044 0.0 S 69 /usr/lib64/firefox/firefox ....
This example uses the -C option to select the processes using the command name firefox. The -L option shows the threads for that process. The -o option again displays selected columns, in this case PID and CMD, along with some other new columns:
- TID = thread identifier
- PCPU = percentage of CPU usage
- STATE = state of the process, as seen earlier in this article. In the example the threads are in the S state, which means interruptible sleep — these processes are waiting for an event to run.
- NLWP = number of light processes; in the example above, firefox is using 69 threads
Finally, you can use ps to track a memory leak. The presence of a memory leak in a process would increase the RAM memory the process has. You can monitor the Resident Set Size (RSS) to have an idea of how much RAM memory a process is using.
$ ps -eF --sort -rss PID PPID C SZ RSS PSR STIME TTY TIME CMD 3015 2352 11 807180 761056 3 14:20 tty2 00:06:47 /usr/lib64/firefox/firefox 3152 3015 7 611589 394944 0 14:20 tty2 00:04:23 /usr/lib64/firefox/firefox 3087 3015 1 598306 350224 0 14:20 tty2 00:00:40 /usr/lib64/firefox/firefox 3715 3015 2 579774 314300 1 14:44 tty2 00:00:46 /usr/lib64/firefox/firefox 2352 2235 2 921991 228908 1 14:15 tty2 00:01:50 /usr/bin/gnome-shell
This command makes use of the –sort -rss option to show the process with the highest RSS at the top. You could sort the processes in the other direction (increasing RSS) using the following option –sort rss.