Section 15.1. Job Control Basics


15.1. Job Control Basics

Recall from Chapter 10 that each active terminal runs a single group of processes, called a session. Each session is made up of process groups, and each process group contains one or more individual processes.

One of the process groups in a session is the foreground process group. The rest are background process groups. The foreground process group may be changed to any process group belonging to the session, allowing the user to switch among foreground process groups. Processes that are members of the foreground process group are often called foreground processes; processes that are not are called background processes.

15.1.1. Restarting Processes

Every process is in one of three states: running, stopped, or zombied. Running processes are terminated by calling the exit() system call or by being sent a fatal signal. Processes are moved between the running and stopped states exclusively through signals generated by another process, the kernel, or themselves.[1]

[1] Stopped processes cannot generate signals, however, so they cannot restart themselves either.

When a process receives SIGCONT, the kernel moves it from the stopped state to the running state; if the process is already running, the signal does not affect its state. The process may catch the signal, with the kernel moving the process to the running state before delivering the signal.

15.1.2. Stopping Processes

Four signals move a running process to the stopped state. SIGSTOP is never generated by the kernel. It is provided to allow users to stop arbitrary processes. It cannot be caught or ignored; it always stops the target process. The other three signals that stop processes, SIGTSTP, SIGTTIN, and SIGTTOU, may be generated by the terminal on which the process is running or by another process. Although these signals behave similarly, they are generated under different circumstances.


This signal is sent to every process in a terminal's foreground process group when a user presses the terminal's suspend key.[2]


When a background process attempts to read from the terminal, it is sent SIGTTIN.


This process is normally generated by a background process attempting to write to its terminal. The signal is generated only if the terminal's TOSTOP attribute is set, as discussed on page 387.


This signal is also generated by a background process calling either tcflush(), tcflow(), tcsetattr(), tcsetpgrp(), tcdrain(), or tcsendbreak().

[2] Normally, the suspend key is Ctrl-Z. The stty program allows users to change the suspend key for a terminal, and Chapter 16 details how a program can change it.

The default action of each of these three signals is to stop the process. They all may be caught or ignored. In both cases, the process is not stopped.

15.1.3. Handling Job Control Signals

Although many applications can be stopped and restarted with no ill effects, other processes need to handle process stops and starts. Most editors, for example, need to modify many of the terminal parameters while they are running. When users suspend the process, they expect their terminal to be restored to its default state.

When a process needs to perform actions before being suspended, it needs to provide a signal handler for SIGTSTP. This lets the kernel notify the process that it needs to suspend itself.

Upon receiving SIGTSTP, the process should immediately perform whatever actions it needs to take in order to allow suspension (such as restoring the terminal to its original state) and suspend itself. The simplest way for the process to suspend itself is by sending itself SIGSTOP. Most shells display messages that indicate which signal caused the process to stop, however, and if the process sent itself SIGSTOP, it would look different from most suspended processes. To avoid this nuisance, most applications reset their SIGTSTP handler to SIG_DFL and send themselves a SIGTSTP.

Processes that require special code for clean suspensions normally need to perform special actions when they are restarted. This is easily done by providing a signal handler for SIGCONT, which performs such actions. If the process suspends itself with SIGTSTP, such special actions probably include setting a signal handler for SIGTSTP.

The following code provides a simple signal handler for both SIGCONT and SIGTSTP. When the user suspends or restarts the process, the process displays a message before stopping or continuing.

  1: /* monitor.c */  2:  3: #include <signal.h>  4: #include <stdio.h>  5: #include <string.h>  6: #include <unistd.h>  7:  8: void catchSignal(int sigNum, int useDefault);  9: 10: void handler(int signum) { 11:     if (signum == SIGTSTP) { 12:         write(STDOUT_FILENO, "got SIGTSTP\n", 12); 13:         catchSignal(SIGTSTP, 1); 14:         kill(getpid(), SIGTSTP); 15:     } else { 16:         write(STDOUT_FILENO, "got SIGCONT\n", 12); 17:         catchSignal(SIGTSTP, 0); 18:     } 19: } 20: 21: void catchSignal(int sigNum, int useDefault) { 22:     struct sigaction sa; 23: 24:     memset(&sa, 0, sizeof(sa)); 25: 26:     if (useDefault) 27:         sa.sa_handler = SIG_DFL; 28:     else 29:         sa.sa_handler = handler; 30: 31:     if (sigaction(sigNum, &sa, NULL)) perror("sigaction"); 32: } 33: 34: int main() { 35:     catchSignal(SIGTSTP, 0); 36:     catchSignal(SIGCONT, 0); 37: 38:     while (1); 39: 40:     return 0; 41: } 


    Linux Application Development
    Linux Application Development (paperback) (2nd Edition)
    ISBN: 0321563220
    EAN: 2147483647
    Year: 2003
    Pages: 168 © 2008-2017.
    If you may any questions please contact us: