Author: Imraan

An overview of Linux processes

A Process is one of the most important fundamental concepts of the Linux operating system. This article focuses on the basics of Linux processes.

Process

A process is an instance of a program running in Linux. This is the basic definition that you might have heard before. Though its simple enough to understand but still lets elaborate a bit for the beginners. Lets quickly create a hello world program in C language :

So we see that a process named ‘hello_world’ is running in the system. Now, try to run the same program in parallel from 2-3 locations and again run the above command. I tried running the program in parallel from three different terminals and here is the output of the above command :

So you see that each instance of the hello_world program created a separate process. Hence we say that process is running instance of a program.

Identifiers associated with a process

Each process has following identifiers associated with it:

Process Identifier (PID)

Each process has a unique identifier associated with it known as process ID. This ID remains unique across the system. For example, if you run the ps command on your Linux box, you will see something like:

The above output is from my Linux box. The second column (PID) gives the process ID of the process being described in the row. You may notice another similar looking column PPID. Well, this gives information of the parent process ID of this process. Any process in the Linux system will have a parent.

User and group Identifiers (UID and GID)

The category of identifiers associated with a process is the user and group identifiers. The user and group ID can further be classified into :

Real user ID and real group ID
These identifiers give information about the user and group to which a process belongs. Any process inherits these identifiers from its parent process.

Effective user ID, effective group ID and supplementary group ID
Ever got an error like “Permission denied”? Well this is a common error that is encountered many times. This error usually occurs when a process does not have sufficient permissions to carry out a task. These three IDs are used to determine the permission that a process has to do stuff that requires special permissions. Usually the effective user ID is same as real user ID but in case its different then it means that process is running with different privileges then what it has by default (ie inherited from its parent). If a process is running with effective user ID ‘0’, this means that this process has special privileges. The processes that have zero effective user ID are known as privileged processes as they are running as superuser. These processes bypass all the permission checks that kernel has in place for all the unprivileged processes.

The init process

In Linux every process has a parent process. Now, one would ask that there has to be some starting point, some process that is created first. Yes, there is a process known as ‘init’ that is the very first process that Linux kernel creates after system boots up. All the process there-on are children of this process either directly or indirectly. The init process has special privileges in the sense that it cannot be killed. The only time it terminates is when the Linux system is shut down. The init process always has process ID 1 associated with it.

Zombie and orphan processes

Suppose there are two processes. One is parent process while the other is child process. In a real time, there can be two scenarios:

The parent dies or gets killed before the child.
In the above scenario, the child process becomes the orphan process (as it has lost its parent). In Linux, the init process comes to the rescue of the orphan processes and adopts them. This means after a chile has lost its parent, the init process becomes its new parent process.

The child dies and parent does not perform wait() immediately.
Whenever the child is terminated, the termination status of the child is available to the parent through the wait() family of calls. So, the kernel does waits for parent to retrieve the termination status of the child before its completely wipes out the child process. Now, In a case where parent is not able to immediately perform the wait() (in order to fetch the termination status), the terminated child process becomes zombie process. A zombie process is one that is waiting for its parent to fetch its termination status. Although the kernel releases all the resources that the zombie process was holding before it got killed, some information like its termination status, its process ID etc are still stored by the kernel. Once the parent performs the wait() operation, kernel clears off this information too.

Daemon process

A process that needs to run for a long period of time and does not require a controlling terminal, these type of processes are programmed in a way that they becomes a daemon processes. For example, monitoring software like key-logger etc are usually programmed as daemon processes. A daemon process has no controlling terminal.

Memory layout of a process

A process can broadly be defined into following segments :

Stack
Stack contains all the data that is local to a function like variables, pointers etc. Each function has its own stack. Stack memory is dynamic in the sense that it grows with each function being called.

Heap
Heap segment contains memory that is dynamically requested by the programs for their variables.

Data
All the global and static members become part of this segment.

Text
All the program instructions, hard-coded strings, constant values are a part of this memory area.

In the example above : – The variable ‘a’ goes into the data segment(specifically into BSS segment that contains all the uninitialized globals) – The variables ‘i’ and ‘ptr’ lie on stack segment. Each function call like memset, memcpy, printf and free will have their separate stack once they get called. – The constant values like “Hello World”, ’15’, ’11’, ‘0’, ‘0XFFFFFFFF’ and all the instructions are part of text segment. – The 15 bytes of memory allocated by the malloc function is allocated on heap. So the pointer ‘ptr’ holds the address of a memory location on heap. Note that heap is shared by all processes, so overuse or corruption of heap might affect other programs running in the system.

Linux process environment

Environment in Linux is a list of ‘variable=value’ information that is used for variety of purposes. Programs, scripts, shells etc use this information for their smooth operation. For example the home directory of the user which is presently logged-in can be accessed by the ‘HOME’ environment variable. List of these environment variables along with their values can be viewed using the ‘env’ command. For example, on my Linux box I could see the following output of the env command :

So we can see that there is a wide list of environment variables available. A user can add an environment variable using the ‘export’ command. In C language, an extern variable char**environ can be used to access this list in a program. A list of functions like getenv(), setenv() etc are available to manipulate the process environment.

Manipulating Linux resource limits

Any process in Linux can get hold of resources like files, memory etc. As always there is a limit to these resources per process. Each resource has a soft and a hard limit associated with it. A soft limit is a temporary limit associated with a resource and can be changed while a hard limit is the cap up to which the soft limit can be changed. Linux provides command line utilities like ‘ulimit’ to manipulate these resource limits. On the other hand the system calls like getrlimit() and setrlimit() can be used to play with these limits from within a C code.

A process is an executing (i.e., running) instance of a program. Processes are also frequently referred to as tasks.A program is an executable file that is held in storage. Storage refers to devices or media that can retain data for relatively long periods of time (e.g., years or even decades), such as hard disk drives (HDDs), optical disks and magnetic tape. This contrasts with memory, whose contents can be accessed (i.e., read and written to) at extremely high speeds but which are retained only temporarily (i.e., while in use or only as long as the power supply remains on).

A program is a passive entity until it is launched, and a process can be thought of as a program in action. Processes are dynamic entities in that they are constantly changing as their machine code instructions are executed by the CPU. Each process consists of (1) system resources that are allocated to it, (2) a section of memory, (3) security attributes (such as its owner and its set of permissions) and (4) the processor state.

The processor state includes the contents of its registers and physical memory addresses. Registers are a very small amount of very fast memory that is built into a processor in order to speed up its operations by providing quick access to commonly used values. A memory address is a location in memory.

An alternative definition of a process is the execution context of a running program, i.e., all of the activity in the current time slot in the CPU. A time slot, also called a time slice or a quantum, is the length of time that each process is permitted to run in the CPU until it is preempted (i.e., replaced) by another process in a time sharingoperating system.

Linux and other Unix-like operating systems have been designed from the ground up as complete time sharing systems, that is, as both multitasking and multi-user systems. A multitasking system is one that allows multiple processes to operate seemingly simultaneously without interfering with each other, and a multi-user system allows multiple users to use the system simultaneously, with each having the illusion of being the sole user.

This intricate but robust time sharing capability is made possible by the ability of the system to both retain many processes in memory at the same time and switch between them fast enough to make it appear as though they are all running simultaneously. If one process crashes (i.e., stops functioning), it will usually not cause other processes to crash because each process runs in its own protected memory space (i.e., area of memory) and is not capable of interacting with other processes except through secure mechanisms managed by the kernel (i.e., the core of the operating system).

Programs and processes are distinct entities. Thus, in a multitasking operating system, multiple instances of a single program can be executing simultaneously, and each instance is a separate process (or processes). For example, if seven users, each with their own keyboard and display device, decide to run the vi text editor at the same time, there will be seven separate instances of vi, each a separate process, although they will all share the same executable file. A single user can likewise simultaneously run seven instances of vi, or some other program.

Another, compatible, definition of a process, for those familiar with the C programming language (in which the kernels and numerous other programs in Unix-like operating systems are written), is the collection of data structures that completely describe how far the execution of the program has progressed. A data structure is a way of storing data in a computer so that it can be used efficiently.

Fortunately, it is not necessary for ordinary users to fully comprehend these definitions in order to understand the basic concept of processes and to know how to use them to control their login sessions (i.e., use of a computer after entering the correct username and password) and make their work more efficient.

The Process Life Cycle

When a computer is booted up (i.e., started), the operating system is loaded into memory. The first part of the operating system that is loaded is vmlinuz, which is the compressed kernel executable.

This results in the creation of init, which is the first process of the session and which becomes the ancestor of all other processes created during that session. The role of init is to read the entries in the file /etc/inittab and execute various programs according to that file. This includes starting the getty process on each of the login terminals, which eventually provides the designated shell for each user.

A shell is a program that provides the traditional, text-only user interface for Unix-like operating systems. Its primary function is to read commands that are typed into a console (i.e., an all-text display mode) or terminal window (an all-text window in a GUI) and then execute (i.e., run) them. A command is an instruction telling a computer to do something, such as start a program.

A program can be started automatically or by a user typing in the name (and correct path if necessary) of the program at the command line (i.e., all-text display mode) and then pressing the ENTER key. This causes the program to be read into memory and executed by the kernel. Some programs create a single process when launched, such as ls (which is used to show the contents of a directory), whereas others, such as OpenOffice (an increasingly popular and open source office suite), initiate a series of processes.

In Unix-like operating systems, each process is given a unique number, referred to as a process identification (PID), when it is created, and this number is used by the system to reference the process. Each process is guaranteed to have a unique PID, which is always a non-negative integer. init always has a PID of 1 because it is always the first process on the system. A very large PID does not necessarily mean that there are anywhere near that many processes on a system, because such numbers are often a result of the fact that PIDs are not immediately reused in order to prevent possible errors.

While a process is running, it can spawn (i.e., give birth to) other processes. Spawning is accomplished through the use of a system call termed a fork (because it splits in two). System calls are clearly defined, direct entry points into the kernel through which processes request services from the kernel.

The first step in spawning a new process is for an existing process to create an identical copy of itself. This copy is then transformed into the new process, and it, in turn, can create additional processes, thereby resulting in multiple generations of processes (i.e., parents spawn children which spawn grandchildren). Analogies can be made with the filesystem hierarchy of Unix-like systems and also with the object hierarchy in an object-oriented programming language (such as Java, in which all classes are descendants of the class named Object).

As is virtually everything else running in a Unix-like operating system, the shell is also a process. (The big exception is the kernel, which is a set of routines that resides continuously in memory and to which all processes have access.) When a user types in a command, the shell spawns a process that executes that command. Unless the user specifies otherwise, the shell typically waits for this child process to be completed before it displays the prompt again to indicate that it is ready for a new command. A prompt, also referred to as a command prompt, is a short text message at the start of each line on a console or terminal window.

If a process is suspended (i.e., temporarily not in use), it becomes eligible for swapping (i.e., transferring) to the swap partition in order to free up space in the main memory for other processes.

During its lifetime, a process will utilize a variety of system resources. They include (1) the processor to run its instructions, (2) the memory to hold it and its data, (3) files within the filesystem and (4) physical devices on the system. The operating system must keep track of each process and the resources it uses in order to manage it and the other processes efficiently, i.e., so that no one process monopolizes the processor or memory.

Viewing Processes

The ps command is used to list the currently running processes and their PIDs. At a bare minimum, two processes will be shown, the shell (usually bash on Linux) and ps, which itself is a process and which dies as soon as its output is displayed. Usually, there will be many more. The following will provide a full listing of the current processes:

ps -aux | less

The -aoption tells ps to list the processes of all users on the system rather than just those of the current user. The -u option tells ps to provide detailed information about each process. The -x option adds to the list processes that have no controlling terminal, such as daemon that are started during booting. In contrast to most commands, the hyphen preceding the option(s) with ps is optional.As the number of processes can be quite long and occupy more than a single screen, the output of ps aux can be piped (i.e., transferred) to the less command, which lets it be viewed one screenful at a time. The output can be advanced one screen forward by pressing the SPACE bar and moved one screen backward by pressing the b key.

Among the information that ps aux provides about each process is the user of the process, the PID, the percentage of CPU used by the process, the percentage of memory used by the process, VSZ (virtual size in kilobytes), RSS (real memory size or resident set size in 1024 byte units), STAT (the process state code), the starting time of the process, the length of time the process has been active and the command that initiated the process. The process state codes include D, uninterruptable sleep; N, low priority; R, runnable (on run queue); S, sleeping; T, traced or stopped; and Z, defunct (zombie).

The processes can also be viewed with the pstree command, which can be used as follows to list all of the processes currently on the system in the form of a tree diagram:

pstree

The addition of the -p option will also show the PIDs:

pstree -p

The processes that are directly connected to the main stem (i.e., a vertical line extending downward from init along the left hand edge of the screen) of the tree are listed by default in alphabetic order. This is in contrast to ps, which by default lists the processes in the order in which they were created. It can be seen that pstree itself is also listed as a process.

Controlling Processes

There are a number of reasons that a user would want to control processes, possibly the most common of which is to close a program that has frozen or crashed. This can be accomplished by using the lethal-sounding kill command.

For example, if the Mozilla web browser freezes and it cannot be closed by using ordinary keyboard commands or mouse clicks, it can in many cases be closed by first using ps aux | less or pstree -p to obtain Mozilla’s PID and then using that PID as an argument (i.e., input) with kill. Thus, if the PID were found to be 1102, then the Mozilla process could be killed with the following:

kill 1102

Another reason that a user might want to control processes is to make use of job control, a feature of the shell that facilitates the handling of multiple processes. Job control can be used to switch processes between the foreground and the background, and it allows programs to be started initially in the background.Running a job in the background is typically done when its execution is expected to take a long time and in order to free the issuing terminal after entering the command. (Some processes are not suitable for running in the background, such as text editors, which occupy the full console or terminal window screen.) Starting a program in the background is accomplished by typing its name followed by an ampersand. For example, typing

gftp &

at the command line starts gftp, an open source FTP (file transfer protocol) program that can be used to send files between computers, in the background. This frees the console or terminal window for use by other commands while gftp is downloading or uploading programs.A process that is running in the foreground can be suspended by simultaneously pressing the CTRL and z keys and can be terminated by simultaneously pressing the CTRL and c keys. The command bg reactivates a suspended program in the background, and the command fg puts a suspended program or a program that is running in the background into the foreground.

Daemons

Daemons are a class of processes that run continuously in the background, rather than under the direct control of a user. The term is derived from the ancient Greek word daimon, which refers to a supernatural being that is intermediate between a human and a god, or similar to a guiding spirit. Daemons are generally easy to recognize because their names end with the letter d.

Daemons are usually launched automatically while a computer is booting up and then wait in the background until their services are required. They typically respond to hardware activity, to network requests or to other programs by performing specified tasks. They can also configure hardware (such as the daemon devfsd, which can provide intelligent management of device entries in the device filesystem on some Linux systems), run scheduled tasks (e.g., crond) and perform a variety of other functions.

Another example is the secure networking daemon, xinetd (eXtended InterNET services Daemon), which is usually launched during booting and listens passively until a program, such as FTP or telnet, requests a connection.

On the Microsoft Windows operating systems, functions comparable to those of daemons are provided by processes called services. However, the term daemon is now sometimes used with regard to those operating systems as well.