Linux/UNIX signal (1)

Source: Internet
Author: User

Signal (1)

The signal is software interruption. Each signal has a name that starts with SIG (for example, SIGABRT dead signal ).

In the header file <signal. h>, these signals are defined as positive integers. There is no signal numbered 0. The kill function has special applications for signal numbered 0.

When a signal appears, the kernel can be processed in one of the following three ways:

1. Ignore this signal

2. Capture Signals

3. Execute the default system action

Signal Function

The simplest interface for UNIX signal mechanism is the signal function.

# Include <signal. h>

Typedef void (* sighandler_t) (int );

Sighandler_t signal (int signum, sighandler_t handler );

In this function, signum is the signal name defined in the header file <signal. h>. The handler value is the constant SIG_IGN, the constant SIG_DFL, or the address of the function to be called after receiving this signal. If SIG_IGN is specified, this signal is ignored to the kernel. If SIG_DFL is specified, it indicates that the action after receiving this signal is the default action of the system. When the function address is specified, the function is called when the signal occurs. We call this processing to capture the signal. This function is called a signal processing program or a signal capturing function. The return value is also a function pointer, which is a pointer to the previous signal processing program.

The following program shows a simple signal processing program that captures two user-defined signals and prints the signal numbers.

#include<stdio.h>#include<signal.h> static voidsig_usr(int);   /* one handler for bothsignals */ int main(void){    if (signal(SIGUSR1, sig_usr) == SIG_ERR)        perror("can't catchSIGUSR1");    if (signal(SIGUSR2, sig_usr) == SIG_ERR)        perror("can't catchSIGUSR2");    for ( ; ; )        pause();} static void sig_usr(intsigno)      /* argument is signal number*/{    if (signo == SIGUSR1)       printf("received SIGUSR1\n");    else if (signo == SIGUSR2)        printf("received SIGUSR2\n");    else        printf("received signal%d\n", signo);}

The execution and output results are as follows:

Chen123 @ ubuntu :~ /User/apue.2e $./A. out &

[1] 5712

Chen123 @ ubuntu :~ /User/apue.2e $Kill-USR1 5712

Received SIGUSR1

Chen123 @ ubuntu :~ /User/apue.2e $Kill-USR2 5712

Received SIGUSR2

Chen123 @ ubuntu :~ /User/apue.2e $Killed 5712

[1] + Terminated./a. out

We call this program in the background and use the kill (1) command to send the signal to it. Note: in UNIX, kill does not mean killing a process. Kill (1) and kill (2) send a signal to a process or process group. Whether the signal terminates the process depends on the signal type and whether the process is scheduled to capture the signal.

Program startup: when a program starts, all signals are in the default or ignored state. The following code in the above program:

If (signal (SIGUSR1, sig_usr) = SIG_ERR)

Perror ("can't catch SIGUSR1 ");

If (signal (SIGUSR2, sig_usr) = SIG_ERR)

Perror ("can't catch SIGUSR2 ");

Indicates that the process captures signals only when they are not ignored. From the two calls of signal, we can see the limitation of this function: the current signal processing method cannot be determined without changing the signal processing method. The sigaction function can determine the processing method of a signal without changing it.

Process Creation: when a process calls fork, its child process inherits the signal processing method of the parent process.

Kill and raise Functions

# Include <sys/types. h>

# Include <signal. h>

Int kill (pid_t pid, int sig );

# Include <signal. h>

Int raise (int sig );

0 is returned for success, and-1 is returned for error. Calling raise (sig) is equivalent to calling kill (getpid (), sig)

There are four possibilities for the pid parameter of kill:

Pid> 0: send the signal to the process whose ID is pid.

Pid = 0: send the signal to all processes in the same process group of the sending process, and the sending process has the permission to send signals to these processes.

Pid <0: send the signal to the Process Group ID equal to the absolute value of the pid, And the sending process has the permission to send the signal to it.

Pid =-1: send the signal to all processes on the system where the sender has the permission to send the signal to them.

Alarm and pause Functions

# Include <unistd. h>

Unsigned intalarm (unsigned int seconds );

You can use the alarm function to set a timer that times out at a specified time in the future. When the timer times out, a SIGALRM signal is generated. If you do not ignore or capture this signal, the default action is to terminate the process that calls the alarm function.

The value of seconds is the number of seconds. It should be noted that after a specified number of seconds, the signal is generated by the kernel. Due to the delay of process scheduling, it takes some time for the process to be controlled to process the signal.

Each process can have only one alarm clock.

# Include <unistd. h>

Int pause (void );

The pause function suspends the calling process until a signal is captured. Pause is returned only when a signal processing program is executed and returned from it. In this case, pause returns-1 and sets errno to EINTR.

Signal Set

We need a data type that can represent multiple signals-signal sets. This data type is used in functions such as siprocmask to tell the kernel that signals in this signal set are not allowed. POSIX.1 defines the data type sigset_t to include a signal set and defines the functions for processing the signal set in the following five cases.

# Include <signal. h>

Intsigemptyset (sigset_t * set );

Intsigfillset (sigset_t * set );

Intsigaddset (sigset_t * set, int signum );

Intsigdelset (sigset_t * set, int signum );

Intsigismember (const sigset_t * set, int signum );

The sigemptyset function initializes the signal set pointed to by the set and clears all signals. The sigfillset function initializes the signal set pointed to by the set to include all signals. Before using a signal set, all applications call sigempty or sigfillset once for the signal set. This is because the C compiler initializes both external and static variables without initial values to 0, but it is not clear whether this corresponds to the implementation of the signal set on the given system.

Once a signal set has been initialized, you can add or delete a specific signal in the signal set. The sigaddset function adds a signal to the existing set, while the sigdelset function deletes a signal from the set. For all functions that use a signal set as a parameter, we always use the signal set address as a parameter transmitted to it.

Sigprocmask Function

# Include <signal. h>

Intsigprocmask (int how, const sigset_t * set, sigset_t * oldset );

Return Value: if the request succeeds, 0 is returned. If the request fails,-1 is returned.

First, if oset is not a null pointer, the current signal shielding word of the process is returned through oset.

Second, if set is a non-null pointer, the how parameter indicates how to modify the current signal shielding word. The following describes the optional values of how.

SIG_BLOCK the signal shielding word of the process is the union of the current signal shielding word and the set pointing to the signal set. Set contains the additional signals we want to block.

SIG_UNBLOC the signal shielding word of this process is the intersection of the current signal shielding word and the signal set complement set referred to by the set. Set contains the signal we want to unblocking.

SIG_SETMASK the new signal shielding word of this process will be replaced by the value of the signal set to which the set points.

If set is a null pointer, the signal shielding word of the process is not changed. The value of how is meaningless.

Sigpending Function

# Include <signal. h>

Intsigpending (sigset_t * set );

The sigpending function returns a signal set. The signals in the sigpending function cannot be delivered because they are blocked during process calling. This signal set is returned through the set parameter.

The following program uses many signal functions described earlier.

#include <stdio.h>#include <signal.h> static void sig_quit(int); intmain(void){   sigset_t    newmask, oldmask,pendmask;    if (signal(SIGQUIT, sig_quit) == SIG_ERR)       perror("can't catch SIGQUIT");    /*    * Block SIGQUIT and save current signal mask.    */   sigemptyset(&newmask);   sigaddset(&newmask, SIGQUIT);   if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)       perror("SIG_BLOCK error"); sleep(5);   /* SIGQUIT here will remain pending */、exit(0);} static voidsig_quit(intsigno){    printf("caught SIGQUIT\n");    if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)        perror("can't reset SIGQUIT");}

Execution and output results:

./A. out

^ \ Generate a signal once (within 5 seconds)

After SIGQUIT pending returns from sleep

Caught SIGQUIT in the signal processing program

After SIGQUIT unblocked is returned from sigprocmask

^ \ Quit again generates a signal

./A. out

^ \ Generate 10 Signals

SIGQUIT pending

Caught SIGQUIT only generates signals once

SIGQUIT unblocked

^ \ Quit again generates a signal

The process blocks the SIGQUIT signal, stores the current signal Shield (for future recovery), and then sleeps for 5 seconds. The exit signal SIGQUIT generated during the second period will be blocked and will not be delivered to the process until the signal is no longer blocked. After the sleep ends in five seconds, check whether the signal is pending and set SIGQUIT to no longer blocked.

When SIGQUIT is set as blocking, we save the old blocking word. In order to unblock the signal, the process signal shielding (SIG_SETMASK) is reconfigured with the old shielding word ).

If an exit signal is generated during sleep, the signal is pending but not blocked. Therefore, it is delivered to the calling process before sigprocmask returns. The output of the program shows that the printf statement in the SIGQUIT processing program is executed first, and then the printf statement after sigprocmask is executed.

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.