Exceptional Control Flow(5)

Putting Processes to Sleep 

The sleep function suspends a process for a specified period of time. 

Sleep returns zero if the requested amount of time has elapsed, and the number of seconds still left to sleep otherwise.

The latter case is possible if the sleep function returns prematurely because it was interrupted by a signal.  

Another function that we will find useful is the pause function, which puts the calling function to sleep until a signal is received by the process. 

Loading and Running Programs 

The execve function loads and runs a new program in the context of the current process

The execve function loads and runs the executable object file filename with the argument list argv and the environment variable list envp.

Execve returns to the calling program only if there is an error such as not being able to find filename.

So unlike fork, which is called once but returns twice, execve is called once and never returns. 

The argv variable points to a null-terminated array of pointers, each of which points to an argument string

By convention, argv[0] is the name of the executable object file.

The list of environment variables is represented by a similar data structure, shown in Figure 8.20.

The envp variable points to a null-terminated array of pointers to environment variable strings, each of which is a name-value pair of the form “NAME=VALUE”. 

After execve loads filename, it calls the startup code described in Section 7.9.

The startup code sets up the stack and passes control to the main routine of the new program, which has a prototype of the form 

int main(int argc, char **argv, char **envp);

When main begins executing in a 32-bit Linux process, the user stack has the organization shown in Figure 8.21.  

From the bottom of the stack (the highest address) to the top (the lowest address) :

First are the argument and environment strings, which are stored contiguously on the stack, one after the other without any gaps.

These are followed further up the stack by a null- terminated array of pointers, each of which points to an environment variable string on the stack.  

The global variable environ points to the first of these pointers, envp[0].

The environment array is followed immediately by the null-terminated argv[] array, with each element pointing to an argument string on the stack.

At the top of the stack are the three arguments to the main routine:

(1) envp, which points to the envp[] array,

(2) argv, which points to the argv[] array, and

(3) argc, which gives the number of non-null pointers in the argv[] array. 

Unix provides several functions for manipulating the environment array :

The getenv function searches the environment array for a string “name=value”. If found, it returns a pointer to value, otherwise it returns NULL. 

setenv and unsetenv are similar:

Programs vs. processes 

A program is a collection of code and data; programs can exist as object modules on disk or as segments in an address space.

A process is a specific instance of a program in execution; a program always runs in the context of some process.

The fork function runs the same program in a new child process that is a duplicate of the parent.

The execve function loads and runs a new program in the context of the current process

While it overwrites the address space of the current process, it does not create a new process. 

The new program still has the same PID, and it inherits all of the file descriptors that were open at the time of the call to the execve function. 

Signals 

In this sec- tion, we will study a higher-level software form of exceptional control flow, known as a Unix signal, that allows processes and the kernel to interrupt other processes

A signal is a small message that notifies a process that an event of some type has occurred in the system. 

Typing “man 7 signal” on the shell command line gives the signal list. 

Each signal type corresponds to some kind of system event.

Low-level hard- ware exceptions are processed by the kernel’s exception handlers and would not normally be visible to user processes. 

Signals provide a mechanism for exposing the occurrence of such exceptions to user processes

examples of signals:

For example, if a process at- tempts to divide by zero, then the kernel sends it a SIGFPE signal (number 8).

If a process executes an illegal instruction, the kernel sends it a SIGILL signal (number 4).

If a process makes an illegal memory reference, the kernel sends it a SIGSEGV signal (number 11).

Other signals correspond to higher-level soft- ware events in the kernel or in other user processes.

For example, if you type a ctrl-c while a process is running in the foreground, then the kernel sends a SIGINT (number 2) to the foreground process.

A process can forcibly terminate another process by sending it a SIGKILL signal (number 9).

When a child process terminates or stops, the kernel sends a SIGCHLD signal (number 17) to the parent

Signal Terminology 

The transfer of a signal to a destination process occurs in two distinct steps: 

(1).  Sending a signal.

The kernel sends (delivers) a signal to a destination process by updating some state in the context of the destination process.  

The signal is delivered for one of two reasons:

(a) The kernel has detected a system event such as a divide-by-zero error or the termination of a child process.

(b) A process has invoked the kill function to explicitly request the kernel to send a signal to the destination process.

A process can send a signal to itself. 

(2) Receiving a signal.

A destination process receives a signal when it is forced by the kernel to react in some way to the delivery of the signal.

The process can either ignore the signal, terminate, or catch the signal by executing a user-level function called a signal handler.

Figure 8.26 shows the basic idea of a handler catching a signal. 

原文地址:https://www.cnblogs.com/geeklove01/p/9258057.html