Processes in Unix/Linux

With the above background information, we are now ready to describe processes in Unix/Linux (Bach 1990; Bovet and Cesati 2005; Silberschatz et al 2009; Love 2005). The reader may correlate the descriptions with processes in the MT system since all the terms and concepts apply equally well in both systems.

1. Process Origin

When an operating system starts, the OS kernel’s startup code creates an initial process with PID=0 by brute force, i.e. by allocating a PROC structure, usually proc[0], initializes the PROC contents and lets running point at proc[0]. Henceforth, the system is executing the initial process P0. This is how most operating systems start to run the first process. P0 continues to initialize the system, which include both the system hardware and kernel data structures. Then it mounts a root file system to make files available to the system. After initializing the system, P0 forks a child process P1 and switches process to run P1 in user mode.

2. INIT and Daemon Processes

When the process P1 starts to run, it changes its execution image to the INIT program. Thus, P1 is commonly known as the INIT process because its execution image is the init program. P1 starts to fork many children processes. Most children processes of P1 are intended to provide system services. They run in the background and do not interact with any user. Such processes are called daemon processes. Examples of daemon processes are

syslogd: log daemon process

inetd : Internet service daemon process

httpd : HTTP server daemon process

etc.

3. Login Processes

In addition to daemon processes, P1 also forks many LOGIN processes, one on each terminal, for users to login. Each LOGIN process opens three FILE streams associated with its own terminal. The three file streams are stdin for standard input, stdout for standard output and stderr for standard error messages. Each file stream is a pointer to a FILE structure in the process HEAP area. Each FILE structure records a file descriptor (number), which is 0 for stdin, 1 for stdout and 2 for stderr. Then each LOGIN process displays a

login:

to its stdout, waiting for users to login. User accounts are maintained in the files /etc/passwd and /etc/ shadow. Each user account has a line in the /etc/passwd file of the form

name:x:gid:uid:description:home:program

in which name is the user login name, x means check password during login, gid is the user’s group ID, uid is the user ID, home is the user’s home directory and program is the initial program to execute after the user login. Additional user account information are maintained in the /etc/shadow file. Each line of the shadow file contains the encrypted user password, followed by optional aging limit information, such as expiration date and time, etc. When a user tries to login with a login name and password, Linux will check both the /etc/passwd and /etc/shadow files to authenticate the user.

4. Sh Process

When a user login successfully, the LOGIN process acquires the user’s gid and uid, thus becoming the user’s process. It changes directory to the user’s home directory and executes the listed program, which is usually the command interpreter sh. The user process now executes sh, so it is commonly known as the sh process. It prompts the user for commands to execute. Some special commands, such as cd (change directory), exit, logout, etc. are performed by sh itself directly. Most other commands are executable files in the various bin directories, such as /bin, /sbin, /usr/bin, /usr/local/bin, etc. For each (executable file) command, sh forks a child process and waits for the child to terminate. The child process changes its execution image to the command file and executes the command program. When the child process terminates, it wakes up the parent sh, which collects the child process termination status, frees the child PROC structure and prompts for another command, etc. In addition to simple commands, sh also supports I/O redirections and multiple commands connected by pipes.

5. Process Execution Modes

In Unix/Linux, a process may execute in two different modes; Kernel mode and User mode, denoted by Kmode and Umode for short. In each mode, a process has an execution image, as shown in Fig. 3.4.

In Fig.3.4, the index i indicates these are the images of process i. In general, the Umode images of processes are all different. However, while in Kmode they share the same Kcode, Kdata and Kheap, which are those of the OS Kernel, but each process has its own Kstack.

A process migrates between Kmode and Umode many times during its life time. Every process comes into existence and begins execution in Kmode. In fact, it does everything of interest in Kmode, including termination. While in Kmode, it can come to Umode very easily by changing CPU’s status register from K to U mode. However, once in Umode it cannot change CPU’s status arbitrarily for obvious reasons. A Umode process may enter Kmode only by one of three possible ways:

(1). Interrupts: Interrupts are signals from external devices to the CPU, requesting for CPU service.

While executing in Umode, the CPU’s interrupts are enabled so that it will respond to any interrupts. When an interrupt occurs, the CPU will enter Kmode to handle the interrupt, which causes the process to enter Kmode.

(2). Traps: Traps are error conditions, such as invalid address, illegal instruction, divide by 0, etc.

which are recognized by the CPU as exceptions, causing it to enter Kmode to deal with the error. In Unix./Linux, the kernel trap handler converts the trap reason to a signal number and delivers the signal to the process. For most signals, the default action of a process is to terminate.

(3). System Calls: System call, or syscall for short, is a mechanism which allows a Umode process to enter Kmode to execute Kernel functions. When a process finishes executing Kernel functions, it returns to Umode with the desired results and a return value, which is normally 0 for success or -1 for error. In case of error, the external global variable errno (in errno.h) contains an ERROR code which identifies the error. The user may use the library function

perror(“error message”);

to print an error message, which is followed by a string describing the error.

Every time a process enters Kmode, it may not return to Umode immediately. In some cases, it may not return to Umode at all. For example, the _exit() syscall and most traps would cause the process to terminate in kernel, so that it never returns to Umode again. When a process is about to exit Kmode, the OS kernel may switch process to run another process of higher priority.

Source: Wang K.C. (2018), Systems Programming in Unix/Linux, Springer; 1st ed. 2018 edition.

Leave a Reply

Your email address will not be published. Required fields are marked *