UNIX Advanced Environment Programming (13) signals-concepts, signal functions, reentrant functions

Source: Internet
Author: User
Tags posix sigint signal signal handler

The signal is a soft interrupt.

Signals provide a way to handle events asynchronously. For example, the user presses the end process key at the terminal to terminate a process prematurely.

?

1 concept of the signal

Each signal has a name, and their names begin with the sig. For example, each time a process invokes the Abort function, a SIGABRT signal is generated.

Each signal corresponds to a positive integer defined in the header file <signal.h>.

No signal corresponding to the integer 0,kill function uses signal number 0 to represent a special case, so signal number 0 is also called the NULL signal (NULL signal).

Each of the following conditions produces a signal:

    • A signal is generated when a user presses a specific key at the terminal. For example, when the user presses the DELETE key (or control-c), an interrupt signal (interrupt Signal,siginit) is generated, which causes a running program to terminate.
    • A hardware exception can generate a signal. Cases that cause hardware exceptions such as dividing by 0, illegal memory references (invalid reference), and so on. This condition is detected by the hardware and notifies the kernel, and the kernel generates corresponding signals to notify the corresponding running process. For example, when a process executes an illegal memory reference, the SIGSEGV signal is triggered.
    • The Kill function allows the current process to send arbitrary signals to other processes or groups of processes. Of course, there is a limit to this approach: we must be the owner of the signal receiving process, or we must be Superuser (Superuser).
    • The kill command acts like the Kill function. This command kills the background process with multiple users.
    • Software anomalies can produce different signals based on different conditions. For example, Sigurg signals are triggered when data accepted in a network connection goes out of bounds.

For the process, the signal is generated randomly, so the process cannot simply determine whether a variable is changing to see if the signal has occurred, but should tell the kernel "When this signal occurs, do the following things".

We tell the kernel what to do when a signal occurs is called a signal processing function. The signal processing function has three functions to choose from:

?

    • ignore the signal . This behavior applies to most signals, except that two signals cannot be ignored: Sigkill and Sigstop. The inability of these two signals is ignored because it provides a foolproof way for the kernel and the superuser to kill or pause the process (a-surefire).
    • capture the signal . When a signal occurs, we tell the process to execute our program. In this program, we can do anything to handle the situation. Two signals Sigkill and sigstop can not be captured.
    • executes the default signal handler . Each signal has a default handler, and most of the signal default handlers terminate the process.

For some signals to occur, the process terminates and a core file is generated that records the memory at the end of the process and can help debug and investigate the termination state of the process.

There are several cases where the core file is not generated:

    • If the process sets the SUID bit (chmod u+s file) and the current user is not the owner of the program file;
    • If the process has set a GUID bit (Set-group-id), and the current user is not the group owner of the program file;
    • If the transfer does not have write permission for the current working directory;
    • If the core file already exists and the user does not have write access to the file;
    • The core file is too large (limited by parameter rlimit_core)?
2 Signal function

function declaration

#include <signal.h>

void (*signal (int signo, void (*func) (int)))) (int);

? ? returns:previous disposition of Signal if OK, Sig_err on ERR.

? function declaration Resolution:

void? (*signal (int signr,? void?) (*handler) (int))) (int);?
================================================?
Handler is a function pointer that points to a single parameter int, returning a function of type void?
Signal is a pointer to a function pointer, this function pointer to an int type and a handler type, the return value is a pointer to a function that has a parameter of int, and the return value is void.

Summarize:?
? ? This complex statement can be expressed in the following 2 simpler types, as follows:?
The first type is as follows:???
typedef? void? (*HANDLER_PT) (int);?
Handler_pt? Signal1 (int signum,handler_pt? ahandler);?
The second type is as follows:?
typedef? void? handler_t (int);?
Handler_t*? Signal2 (int signum,? handler_t*? ahandler);?
------------------------------------------------------?
These two form results are equivalent, but there are differences, the first form defines the function pointer type,?
sizeof (HANDLER_PT) =4//borland? C++? 5.6.4? For? Win? 32,windos? Xp? 32? Platform?
The second form defines the function type, and if he uses sizeof (handler_t), it prompts:?
sizeof? May? Not? Be? Applied? To? A? function

Parameter description:

    • Signo: Signal Name
    • Func: Three selection of values: constant Sig_ign, constant SIG_DFL, or address of the signal processing function. If the value of Func is sig_ign, the signal occurs ignoring processing (except for two signals Sigkill and sigstop). If the value of Func is SIG_DFL, the default handler for the signal is called.

In the above declaration parsing we can see that using TypeDef simplifies the declaration of the signal function, and subsequent calls to the signal function will use the simplified declaration:

typedef void Sigfunc (int);

Sigfunc *signal (int, sigfunc *);

?

? Example

The purpose of this example is to capture two user-defined signals and print the relevant signal information.

Use the function pause to suspend the program and know that the signal is received.

Code

#include "Apue.h"

?

Static void sig_usr (int);? /* One handler for both signals */

?? ? ? ? ?

int ???

Main (void)

{ ? ? ? ?

? ? if (Signal (SIGUSR1, sig_usr) = = Sig_err)

???? ? Err_sys ("can ' t catch SIGUSR1");

? ? if (Signal (SIGUSR2, sig_usr) = = Sig_err)

???? ? Err_sys ("can ' t catch SIGUSR2");

? ? for ( ; ; )

? ? ? ? Pause ();

}? ?

?? ?

Staticvoid

sig_usr (int signo)? ?? /* argument is signal number */

{? ?

? ? if (Signo = = SIGUSR1)

???? printf ("received SIGUSR1\ n");

? ? Else if (Signo = = SIGUSR2)

???? printf ("received SIGUSR2\ n");

? ?? Else

? ? ? ?? Err_dump ("received signal %d\n", Signo);

}

Execution Result:

At execution time, we let the program run in the background and then call the KILL command to send a signal to the process.

Kill does not really kill the process, but simply sends a signal. So kill doesn't exactly describe the purpose of the command.

When we call the Kill 2081 command, the process is terminated because the signal is not processed in the signal processing function, and the default handler for that signal is the terminating process.

?

Program start State

When the program executes, all signals are in the default state or are ignored.

If the program calls the EXEC system function, it will change the signal's custom handler to its default handler because the address of the handler in the original program is meaningless for the new program.

For example, in an interactive shell, starting a background process that sets the process's interrupt and exit signal processing action is ignored, so that when the user types the interrupt command in the shell, the foreground process is only interrupted without affecting the background process.

This example also tells us a limitation of the signal function: we cannot confirm the processing of some signals of the current process unless we change them now. Later we will learn the Sigaction function to confirm the processing action of a signal without changing them.

?

Program creation

When the fork function is called, the child process inherits the signal handler function of the parent process. Because the child process copies the memory of the parent process, the address of the signal handler function is also meaningful for the child process.

?

3 unreliable signal (unreliable signals)

In the early Unix system, the signal was unreliable.

Unreliable means that the signal is likely to be lost. That is, the signal has occurred, but the process has not captured it.

We want the kernel to remember the signal, and when we are ready, tell us that the signal is happening and let's deal with it.

Early systems, there is a problem with the implementation of the signal mechanism: when the signal occurs, the signal processing function is executed, the signal processing function is set as the default signal processing program. Thus, the early program framework for signaling is as follows:

The problem with this code is that after the SIGINT signal has occurred and there is a time difference between the signal processing function and the reset to Sig_int, a SIGINT signal may occur again within this time difference.

If the second SIGINT occurs before the signal processing function is reset, it performs its default processing action, which is to terminate the process.

One problem with early implementations is that if a process does not want a signal to occur, it can only choose to ignore it, and it cannot turn off the signal.

One usage scenario is that we don't want to be interrupted by a signal, but want to remember that they have happened. The code might look like this:

Here, we assume that the signal only happens once.

The purpose of the code is: we wait for the signal to occur, before the signal occurs, the process stops, waits.

The problem with the code is that there is a time difference that may occur if the code executes the sequence as follows:

1 Signal Occurrences

2 while (Sig_int_flag = = 0)

3 sig_int_flag= 1

4 Pause ()

At this point, the process pauses pending, waiting for the signal to occur, but in fact the signal has already occurred. This leads to a signal not being captured.

?

4 interruptible system calls

One feature of the early UNIX operating system is that if a process is blocked in a "slow" system call, the process receives a signal that the process is interrupted. The system call returns an error, and errno is set to Eintr.

System calls are divided into two categories: slow system calls and other system calls. Slow system calls are those system calls that can be permanently blocked. Slow system calls include:

    • The read data function may block the caller if the data is not in a specific format;
    • The Write data function may block the caller if the data cannot be received immediately in a specific format.
    • Open a file in a format
    • The pause function and the wait function
    • Specific IOCTL operations
    • Some inter-process communication functions

For interruptible system calls, we need to process errno eintr in code:

To avoid the need to explicitly handle interruptible system calls, some interruptible system calls automatically restart when blocking occurs.

These interruptible system calls that automatically restart include: IOCTL, read, Readv, write, Writev, wait, and waitepid.

If some apps do not want these system calls to restart automatically, the system call can be set Sa_restart separately.

?

5 reentrant functions

The sequence of instruction execution of the program is disrupted by the occurrence of the signal.

However, in the signal processing function, it is impossible to know the execution of the original process.

If the original process allocates memory or frees memory, or calls a function that modifies the static variable and calls the function again in the signal handler function, unexpected results occur.

Functions that can be safely called in a signal processing function are called reentrant functions, also called asynchronous signal security functions. In addition to guaranteeing reentrant, these functions also block signals that may cause inconsistent results.

If the function satisfies one or more of the following conditions, it is a non-reentrant function:

    • Using the static data structure
    • Call malloc or free
    • Functions in the standard IO library, because most of the standard IO functions use global data structures

?

6 SIGCLD semantics

The two signals that have been easily confused are SIGCLD and SIGCHLD.

The SIGCLD comes from System V, and SIGCHLD is from BSD and posix.1.

BSD sigchld semantics: When this signal occurs, the state of the child process is changed, and we need to call the wait function to confirm the change of state.

For System V systems, the processing of signal SIGCLD is described as follows:

    1. If the process set signal SIGCLD processing action is sig_ign, the process's child process will not become a zombie process. This is different from the default processing action (SIG_DFL), although the default action is also ignored, but for sig_ign, if the wait function is subsequently called, the calling process blocks until all child processes are terminated, wait returns 1, and the setting is errno to Echild. The default processing action (SIG_DFL) is not followed by an action.
    2. If we set a capture on the signal SIGCLD, the kernel immediately checks to see if any child processes are waiting, if any, to call the signal handler function.

?

7 reliable signals and their semantics

? We define several signal-related concepts first:

    • Signal Generation : If an event causes a signal to occur, it is called a signal generation. This event may be a hardware exception, a software condition, a terminal-generated signal, or a signal passed by the kill function. When the signal is generated, the kernel needs to set a flag bit in the process table.
    • Signal Delivery : When the signal processing function is executed, the signal is served.
    • Signal hangs : The time between signal generation and delivery is called a signal hang.
    • Signal blocking : The process can choose not to receive a signal transmission, called blocking the signal. If the processing action of the blocked signal is the default handler or is captured, the signal will remain in the suspended state until the process has unblocked the signal or changed the signal's processing action to ignore. The system determines how the blocked signal is handled when the signal is transmitted, rather than when the signal is generated. The function of sigpending is to let the process decide which signals are blocked and suspended.

Reliability mechanism, different standards for the exception of different treatment:

    • If a blocked signal is generated multiple times, the kernel simply passes the signal once.
    • If multiple signals are waiting to be communicated, POSIX.1 does not pay attention to the order in which the signals are communicated, and the rationale for Posix.1 standard ensures that the signals associated with the current state of the process are communicated first.
    • Each process has a signal mask to determine whether to block a signal, each bit of the signal mask corresponds to a signal, if you want to block a signal, the corresponding signal is set to 1.
    • Data structure sigset_t is defined to record a signal mask (signal mask)

?

? References:

"Advanced programming in the UNIX envinronment 3rd"

UNIX Advanced Environment Programming (13) signals-concepts, signal functions, reentrant functions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.