Tuesday, August 28, 2007

Linux: Process, Signal & System Overview


System Cause a program to run from inside another program and thereby create a

New process

Fork create a new process

Duplicating a process image

This system call duplicates the current process, creating a new entry in the process table with many of the same attributes as the current process. The new process is almost identical to the original, executing the same code but with its own data space, environment, and file descriptors. Combined with the exec functions, fork is all we need to create new processes.

Exec family Run a given program in the process

Replacing a process image

Wait, waitpid

Wait3, wait4 waiting for a process

Arrange for the parent process to wait until the child finishes before continuing by calling wait.

The wait system call causes a parent process to pause until one of its child processes is stopped.


Killing a Process

You can kill a running process with the kill command. Simply specify on the command line the process ID of the process to be killed. The kill command works by sending the process a SIGTERM, or termination, signal.1 This causes the process to terminate, unless the executing program explicitly handles or masks the SIGTERM signal. Signals are described in Section 3.3,“Signals.”

1.You can also use the kill command to send other signals to a process

What’s the difference? The SIGTERM signal asks a process to terminate; the process may ignore the request by masking or ignoring the signal.The SIGKILL signal always kills the process immediately because the process may not mask or ignore SIGKILL.

If a process receives one of these signals without first arranging to catch it, the process will be terminated immediately. Usually, a core dump file is created. This file, called core and placed in the current directory, is an image of the process that can be useful in debugging.

Signal

(signals are generated by software. interrupts are generated by interrupts so signals are software interrupts )

A signal is a special message sent to a process. Signals are asynchronous; when a process receives a signal, it processes the signal immediately, without finishing the current function or even the current line of code.There are several dozen different signals, each with a different meaning.

Signals are software generated interrupts that are sent to a process when a event happens. Signals can be synchronously generated by an error in an application, such as SIGFPE and SIGSEGV, but most signals are asynchronous.

Because signals are asynchronous, the main program may be in a very fragile state when a signal is processed and thus while a signal handler function executes. Therefore, you should avoid performing any I/O operations or calling most library and system functions from signal handlers. A signal handler should perform the minimum work necessary to respond to the signal, and then return control to the main program (or terminate the program). In most cases, this consists simply of recording the fact that a signal occurred.The main program then checks periodically whether a signal has occurred and reacts accordingly. It is possible for a signal handler to be interrupted by the delivery of another signal. While this may sound like a rare occurrence, if it does occur, it will be very difficult to diagnose and debug the problem. (This is an example of a race condition, discussed in Chapter 4,“Threads,” Section 4.4,“Synchronization and Critical Sections.”) Therefore, you should be very careful about what your program does in a signal handler.

Even assigning a value to a global variable can be dangerous because the assignment may actually be carried out in two or more machine instructions, and a second signal may occur between them, leaving the variable in a corrupted state. If you use a global variable to flag a signal from a signal-handler function, it should be of the special type sig_atomic_t. Linux guarantees that assignments to variables of this type are performed in a single instruction and therefore cannot be interrupted midway. In Linux, sig_atomic_t is an ordinary int; in fact, assignments to integer types the size of int or smaller, or to pointers, are atomic. If you want to write a program that’s portable to any standard UNIX system, though, use sig_atomic_t for these global variables.

Signals are not presented to the process immediately they are generated., they must wait until the process is running again. Every time a process exits from a system call its signal and blocked fields are checked and, if there are any unblocked signals, they can now be delivered. This might seem a very unreliable method but every process in the system is making system calls, for example to write a character to the terminal, all of the time. Processes can elect to wait for signals if they wish, they are suspended in state Interruptible until a signal is presented. The Linux signal processing code looks at the sigaction structure for each of the current unblocked signals.

system

We can cause a program to run from inside another program and thereby create a new process by using the system library function.

#include

int system (const char *string);

The system function runs the command passed to it as a string and waits for it to complete. The command is executed as if the command

$ sh -c string

has been given to a shell. system returns 127 if a shell can’t be started to run the command and -1 if another error occurs. Otherwise, system returns the exit code of the command.

We can use system to write a program to run ps for us. While this is not tremendously useful in and of itself, we’ll see how to develop this technique in later examples. We also don’t check that the system call actually worked for the sake of simplicity in the example.

#include

#include

int main()

{

printf(“Running ps with system\n”);

system(“ps -ax”);

printf(“Done.\n”);

exit(0);

}

When we compile and run this program, system1.c, we get the following:

$ ./system1

Running ps with system

PID TTY STAT TIME COMMAND

1 ? S 0:05 init

2 ? SW 0:00 [keventd]

...

1262 pts/1 S 0:00 /bin/bash

1273 pts/2 S 0:00 su -

1274 pts/2 S 0:00 -bash

1463 pts/1 S 0:00 oclock -transparent -geometry 135x135-10+40

1465 pts/1 S 0:01 emacs Makefile

1480 pts/1 S 0:00 ./system1

1481 pts/1 R 0:00 ps -ax

Done.

Because the system function uses a shell to start the desired program, we could put it in the background by changing the function call in system1.c to the following:

system(“ps -ax &”);

When we compile and run this version of the program, we get

$ ./system2

Running ps with system

PID TTY STAT TIME COMMAND

1 ? S 0:05 init

2 ? SW 0:00 [keventd]

...

Done.

$ 1246 ? S 0:00 kdeinit: klipper -icon klipper -miniicon klipper

1274 pts/2 S 0:00 -bash

1463 pts/1 S 0:00 oclock -transparent -geometry 135x135-10+40

1465 pts/1 S 0:01 emacs Makefile

1484 pts/1 R 0:00 ps -ax

How It Works

In the first example, the program calls system with the string “ps -ax”, which executes the ps program. Our program returns from the call to system when the ps command has finished. The system function can be quite useful but is also limited. Because our program has to wait until the process started by the call to system finishes, we can’t get on with other tasks.

In the second example, the call to system returns as soon as the shell command finishes. Because it’s a request to run a program in the background, the shell returns as soon as the ps program is started, just as would happen if we had typed

$ ps -ax &

at a shell prompt. The system1 program then prints Done. and exits before the ps command has had a chance to finish all of its output. The ps output continues to produce output after system1 exits. This kind of process behavior can be quite confusing for users. To make good use of processes, we need finer control over their actions. Let’s look at a lower-level interface to process creation, exec.

The system function can be quite useful but is also limited. Because program has to wait until the process started by the call to system finishes, we can’t get on with other tasks.

In general, using system is a far from ideal way to start other processes, because it invokes the desired program using a shell. This is both inefficient, because a shell is started before the program is started, and also quite dependent on the installation for the shell and environment that are used.

0 comments;Click here for request info on this topic:

Post a Comment