Core signal Processing & CPU8 Universal Registers

Source: Internet
Author: User
Tags sigint signal signal handler

Core Signal Processing Reference:


The signal is essentially a simulation of the interrupt mechanism at the software level (attention to distinguish interrupts, anomalies, signals), which mainly have the following sources:

    1. Program error: Except 0, illegal memory access ...
    2. External signals: Terminal CTRL-C generates SGINT signal, timer expires SIGALRM ...
    3. Explicit request: The KILL function allows a process to send any signal to another process or process group.
-2 PID

Linux currently supports 64 types of signals. The signal is divided into non-real-time signal (unreliable signal) and real-time signal (reliable signal) two types, corresponding to the Linux signal value of 1-31 and 34-64. (in detail, see part II)

The signal is asynchronous, and a process does not have to wait for the signal to arrive by any action, in fact, the process does not know exactly when the signal arrives. This paper focuses on the signal processing mechanism of Linux, the more information about the signal can be referenced here.

In general, when a process receives a signal, the following behavior occurs:

The response of the process to the signal

    1. Ignoring signals: Most signals can be ignored, except for Sigstop and Sigkill signals (this is the means by which super users kill or stop arbitrary processes).
    2. Capture signal: Registers a signal processing function, which processes the specific signal produced.
    3. Let the signal default action work: The UNIX kernel defines the default action in 5 scenarios:
      • A) aborted abort: Terminates the process and produces a core file.
      • b) Terminate stop: Terminates the process without generating a core file.
      • c) Ignore: Ignore signal.
      • d) Suspend suspend: Suspend process.
      • E) Continue continue: If the process is suspended, the resume process, otherwise ignores this signal.

Registering Signal processing functions

If you want the process to capture a signal and then make the appropriate processing, you need to register the signal processing function. Similar to interrupts, the kernel also prepares a signal vector table for each process , which records the processing mechanism of each signal, by default invoking the default processing mechanism. When the process registers a signal handler for a signal, the kernel invokes the registered function when that signal occurs.

The Register signal handler function is called by the system signal (), sigaction (). where signal () is implemented on the basis of a reliable signal system invocation, it is a library function. It has only two parameters, does not support signal transmission information, mainly for the first 32 kinds of non-real-time signal installation, and sigaction () is a newer function (implemented by two system calls: Sys_signal and Sys_rt_sigaction), three parameters, support signal transmission information, Mainly used in conjunction with Sigqueue () system calls, of course, sigaction () also supports the installation of non-real-time signals. Sigaction () is better than signal () mainly reflected in the supporting signal with parameters. If you want to get more, you can also refer to this section.

signal processing mechanism under Linux

How does the process discover and accept signals?

We know that the signal is asynchronous, that a process cannot wait for the signal to come, and that the signal will come, so how does the process discover and accept the signal? In fact, the reception of the signal is not done by the user process, but by the kernel agent. When a process P2 sends a signal to another process P1, the kernel accepts the signal and places it in the P1 signal queue. When the P1 again falls into the kernel state, the signal queue is checked and the corresponding signal processing function is tuned according to the corresponding signal. As shown in the following:

signal detection and response time

Just now we said that when P1 again into the kernel, it would check the signal queue. So when will P1 get into the kernel again? At what time will the signal queue be detected when trapped in the kernel?

    1. The current process returns to the eve of the user space from system space after it enters system space due to system calls, interrupts, or exceptions.
    2. The current process is awakened after it enters sleep in the kernel (must be in the system call), or is returned to the user space prematurely due to the presence of a non-negligible signal.

Enter Signal processing function

After discovering the signal, according to the signal vector, know the processing function, then how to enter the signal processing program, and how to return it?

We know that the signal processing function provided by the user process is in the user state, and we find that the signal processing function is in the kernel state , so we need to run from the kernel state to the user state to execute the Signal processing program , after execution Also return to the kernel state . The process is as follows:

See, the whole process of processing signals is this : the process due to system calls or interrupts into the kernel, the completion of the corresponding task to return user space before the eve, check the signal queue, if there is a signal, according to the Signal vector table find signal processing function, set "frame" after , jump to the user state to perform the signal processing function. After the signal processing function completes, it returns to the kernel state, sets "frame", and then returns to the user state to continue executing the program.

In the above passage, I mentioned "frame", what is frame? So why set frame? Why do I have to return to the kernel state after executing the signal processing function?

What do you mean frame?

When calling a subroutine, the stack is stretched down (logically upwards) because the return address of the subroutine needs to be saved on the stack, as well as the subroutine often has local variables and takes up space in the stack. In addition, parameters that are called when subroutines are also in the stack. The deeper the subroutine call is nested, the more layers the stack stretches. Each of these levels in the stack is called a "frame", or frame.

(Note: The frame is a concept that is seen with the BT command in GDB)

In general, when the subroutine and the program that calls it are in the same space, the stack stretches, that is, the frame in the stack is built, the process is mainly as follows:

    1. The call command will return the address to the stack (automatic)
    2. Pressing the call parameter with the push command
    3. Adjust the stack pointer to assign local variables

We know that when the process is in the kernel state, the interrupt scene is saved in the stack. Because the user state and the kernel state are two runlevel, two different stacks are used.

Note: The above sentence is particularly important, be sure to note that it is two stacks.

After the signal processing function is found, the Do_signal function first saves the EIP in the kernel stack as OLD_EIP, and then replaces the EIP with the address of the signal processing function, then subtracts a certain value from the "original ESP" (that is, the user-state stack address) stored in the kernel. The goal is to enlarge the user-state stack and then save the content on the kernel stack to the user stack, which is the process of setting up the frame. It is worth noting that the following two points:

    1. The value of the EIP is set to the address of the signal processing function, because once the process returns to the user state, it is necessary to execute the signal processing program, so the EIP should point to the signal handler instead of the original address that should be executed.
    2. The reason to copy frame from the kernel stack to the user stack is because the process returns from the kernel to the user state will clean up the kernel stack (similar function call) used in this call, the kernel stack is too small, can not simply save another frame on the stack (imagine nested signal processing), And we need to EAX (System call return value), EIP this information so that after the execution of the signal processing function can continue to execute the program, so copy them to the user state stack to save them.

Note: The middle section is omitted. After the signal is discovered, to execute the signal processing function, so register EIP to point to the signal processing function instead of the original subsequent execution address. Then after the call is over, return to the kernel state, for the next paragraph, the main two points.

what happens when the signal processing function finishes executing?

After the signal handler executes, the process calls the Sigreturn () system call back to the kernel again, (a) to see if there are any other signals to be processed, and if not, then the kernel will do some cleanup work before (ii) the saved frame reverts to the kernel stack, the value of the recovery Eip is OLD_EIP, and then the user space is returned, and the program continues to execute . At this point, the kernel passes through the signal processing once (or several times).

Register Device16-bit CPU Universal Registers Total 8: Ax,bx,cx,dx,bp,sp,si,di. Eight registers can be used as normal data registers. But some have special uses: AX is accumulator, CX is counter, BX,BP is base register, Si,di is the variable address register, BP can also be base pointer, SP is stack pointer. 32-bit CPU general-purpose registers Total 8: Eax,ebx,ecx,edx,ebp,esp,esi,edi function and above almost NOTE: EAX: System call return value EIP: Location of the next execution ESP: Stack address

Non-real-time, real-time signals andSignal Correlation function


Signals that are located between Sigrtmin and Sigrtmax are reliable signals that overcome the potential loss of the signal. While Linux supports the new version of the signal installation function sigation () and the signal sending function sigqueue (), it still supports the early signal () signal installation function, which supports the signal sending function kill ().

The reliable and unreliable signal is only related to the signal value, and is independent of the sending and installing function of the signal. Currently, signal () in Linux is implemented through the sigation () function, so even if the signal is installed through the signal (), the signal handler function is not required to be called at the end of the signal processing function. At the same time, the real-time signal supported by signal () is queued and will not be lost.

For the current Linux two signal installation functions: signal () and sigaction (), they can not turn sigrtmin previous signal into a reliable signal (neither queuing, still may be lost, is still unreliable signal), It also supports queuing for signals after sigrtmin. The biggest difference between these two functions is that the signals that are installed by the Sigaction can pass information to the signal processing function, and the signals that are installed by signal cannot pass information to the signal processing function. The same is true for signal-sending functions.

2.2 Real-time and non-real-time signals

Early UNIX systems defined only 32 types of signals, and the first 32 signals had predefined values, each with a definite purpose and meaning, and each signal had its own default action. If you press the CTRL ^c of the keyboard, the SIGINT signal is generated, and the default response to that signal is the process termination. The latter 32 signals represent real-time signals and are equivalent to the reliable signals described earlier. This ensures that multiple real-time signals sent are received.

Non-real-time signals do not support queueing, are unreliable signals, real-time signal support queuing, are reliable signals.

The list of supported Linux signals is as follows. Many of the signals are related to the architecture of the machine.

signal Value The default processing action causes the signal to be signaled sighup1A terminal hangs or the control process terminates SIGINT2A Keyboard interrupt (such as the break key is pressed) Sigquit3C Keyboard exit key is pressed Sigill4C illegal Directive SIGABRT6C by Abort (3) Exit instructions issued by SIGFPE8C Floating-point exception Sigkill9AEF kill Signal SIGSEGV OneC Invalid memory reference Sigpipe -a pipeline rupture: write a pipe without a read port Sigalrm -A by Alarm (2) signals emitted by sigterm theA termination Signal SIGUSR1 -,Ten, -A user-defined signal 1SIGUSR2 to, A, -A user-defined signal 2SIGCHLD -, -, -B Sub-process end signal Sigcont +, -, -process continues (a process that has been stopped) SIGSTOP -, +, atDEF terminating process SIGTSTP -, -, -D Control Terminal (TTY) press the stop button Sigttin +, +, -D Background process attempts to read Sigttou from the control terminal A, A, -D background process attempts to write from the control terminal
View Code

Signals are registered in the target process

There is a soft interrupt signal field in the table entry in the process table, and each bit in the field corresponds to a signal. The method by which the kernel sends a soft interrupt signal to a process is the bit that corresponds to the signal field of the process table entry where the process is located. If the signal is sent to a process that is sleeping, the process is awakened if the process sleeps at a priority that can be interrupted , otherwise only the corresponding bit of the signal field in the process table is set, not the process is awakened. If you send to a process that is in a running state, only the appropriate domain is placed.

The TASK_STRUCT structure of the process has data members about the outstanding signals in this process : struct sigpending pending:

struct sigpending{

struct Sigqueue *head, *tail;

sigset_t signal;


(Note: The above sigqueue and sigset_t are used for real-time and non-real-time signals respectively)

When a real-time signal is sent to a process, regardless of whether the signal has been registered in the process, it will be re-registered once, so the signal is not lost, so the real-time signal is also called "reliable signal." This means that the same real-time signal can occupy multiple sigqueue structures in the pending signal information chain of the same process (the process receives a real-time signal, assigns it a structure to register the signal information, and adds the structure to the left of the pending signal chain, i.e. all real-time signals that are born are registered in the target process).

When a non-real-time signal is sent to a process, if the signal is already registered in the process (indicated by the sigset_t signal), the signal is discarded, causing the signal to be lost. Therefore, the non-real-time signal is also called "unreliable signal". This means that the same non-real-time signal in the process of the pending signal information chain, at most, occupy a sigqueue structure.

In short, the signal registration is not related to the function that sends the signal (such as Kill () or Sigqueue (), and the signal installation function (signal () and sigaction ()), only with the signal value (signal value less than sigrtmin signal is registered at most once, Signal value between Sigrtmin and Sigrtmax, as long as the process is received to be registered)

3.3 Execution and logoff of signals

The time the kernel handles a signal received by a process is when a process returns to the user state from the kernel state . Therefore, when a process is running in the kernel state, the soft interrupt signal does not work immediately, and is not processed until it returns to the user state . The process will return to the user state only after processing the signal, and the process will not have an unhandled signal in the user state .

If the process receives a signal to be captured, the process executes the user-defined function from the kernel state when it returns to the user state. And the way to execute user-defined functions is ingenious , the kernel is to create a new layer on the user stack, which sets the value of the return address to the address of a user-defined handler, so that the process returns to the user-defined function when the kernel returns to the top of the pop-up stack. Returning to the top of the stack from the function returns the place where the kernel was originally entered . The reason for this is that the user-defined handler cannot and does not allow execution in the kernel state (if the user-defined function is running in the kernel state, the user can get any permissions).

5 Sending of signals

The main functions for sending signals are: Kill (), raise (), Sigqueue (), Alarm (), Setitimer (), and Abort ().

5.1 Kill ()

#include <sys/types.h>

#include <signal.h>

int Kill (pid_t pid,int Signo)

This system call can be used to send any signal to any process or process group. The value of the parameter PID is the receiving process of the signal

Pid>0 process with process ID PID

Pid=0 processes for the same process group

PID<0 Pid!=-1 Process Group ID is-pid for all processes

Pid=-1 processes with process IDs greater than 1 in addition to the sending process itself

The Sinno is a signal value that, when it is 0 o'clock (i.e. an empty signal), actually does not send any signal, but does error checking as usual, so that it can be used to check whether the target process exists and whether the current process has permission to send a signal to the target (the root-privileged process can send a signal to any process, A non-root process can only send a signal to a process that belongs to the same session or to the same user.

Kill () is most commonly used for signal sending at pid>0. When the call executes successfully, the return value is 0, the error returns 1, and the corresponding error code errno is set. Here are some of the error codes that may be returned:

EINVAL: The specified signal sig is not valid.

Esrch: Parameter pid The specified process or process group does not exist. Note that the process that exists in the process table entry may be a zombie process that has not been recovered by wait, but has terminated execution.

Eperm: The process does not have the power to send this signal to the specified receiving signal. Because a process is allowed to send a signal to the process PID, it must either have root authority, or the UID or euid of the process that issued the call is the same as the UID or save user ID (Savedset-user-id) of the process that you specify to receive. If the parameter PID is less than-1, that is, the signal is sent to a group, the error indicates that a member process in the group cannot receive the signal.

5.2 Sigqueue ()

#include <sys/types.h>

#include <signal.h>

int Sigqueue (pid_t pid, int sig, Const Union Sigval Val)

The call returns 0 successfully; otherwise, 1 is returned.

Sigqueue () is a relatively new signaling system call, mainly for real-time signals (of course, the first 32), supporting the signal with parameters, and function sigaction () with the use.

5.3 Alarm ()

#include <unistd.h>

unsigned int alarm (unsigned int seconds)

The system calls alarm to schedule the kernel to emit a SIGALRM signal for the calling process after the specified seconds seconds. If the specified parameter seconds is 0, the SIGALRM signal is no longer sent. The next setting cancels the previous setting. The call returns a value that is the time remaining between the last scheduled call to the send or 0 because there is no previous scheduled call.

Note that when used, the alarm is only set to send a signal once, and if it is to be sent multiple times, it will be called multiple times using alarm.

5.4 Setitimer ()

Many programs in the current system no longer use the alarm call, but instead use the Setitimer to set the timer, using the Getitimer to get the state of the timer, the declaration format of the two calls is as follows:

int Getitimer (int which, struct itimerval *value);

int Setitimer (int which, const struct itimerval *value, struct itimerval *ovalue);

Add the following header file to the process that uses the two calls:

#include <sys/time.h>

5.5 Abort ()

#include <stdlib.h>

void abort (void);

Sends a sigabort signal to the process, by default the process exits abnormally, and of course it can define its own signal processing function. Even if the sigabort is set to block by the process, the sigabort can still be received by the process after calling abort (). The function has no return value.

5.6 Raise ()

#include <signal.h>

int raise (int signo)

Sends a signal to the process itself, and the parameter is the signal value that is about to be sent. The call returns 0 successfully; otherwise, 1 is returned.

6 signal set and signal set operation function:

A signal set is defined as a data type:

typedef struct {

unsigned long sig[_nsig_words];

} sigset_t

A signal set is used to describe a set of signals, each of which occupies one bit. All the signals supported by Linux can appear in the signal set in whole or in part, and are mainly used in conjunction with the signal blocking correlation function.

7 signal blocking and signal pending:

Each process has a set of signals to describe which signals will be blocked when they are delivered to the process, and all signals in that set will be blocked after they are delivered to the process. The following are several functions related to signal blocking:

#include <signal.h>

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

int sigpending (sigset_t *set));

int sigsuspend (const sigset_t *mask));

The Sigprocmask () function can operate on the signal set according to the parameter how, there are three main operations:

Sig_block adding a set to a signal set in the current blocking signal set of the process

Sig_unblock if a process blocking signal set contains a signal set pointing to the signal set, the blocking of the signal is lifted

Sig_setmask update process block signal set for set-pointing signal set

Sigpending (sigset_t *set) obtains all signals that are currently delivered to the process but is blocked, returning the result in the set-directed signal set.

Sigsuspend (const sigset_t *mask)) is used to temporarily replace a process's signal mask with mask before receiving a signal, and pauses the process execution until the signal is received. The signal mask before the call is resumed after Sigsuspend returns. After the signal processing function is complete, the process will continue to execute. The system call always returns-1, and the errno is set to Eintr.

8 Signal Application Example

The signal application under Linux is not as scary as it is imagined, and there are only three things programmers have to do:

Installation Signal (Sigaction () recommended);

Implement three-parameter signal processing function, handler (int signal,struct siginfo *info, void *);

To send a signal, it is recommended to use Sigqueue ().

In fact, for some signals, it is sufficient to install the signal (the signal processing method is either default or ignored). The other things you might want to do are just a few operations related to the signal set.

Note: The signal can also pass parameter information. Examples are as follows:
Example Two: Signal transmission additional information consists of two instances: sending signals to the process itself and passing pointer parameters # # #<signal.h>#include<sys/types.h>#include<unistd.h>voidNew_op (int, siginfo_t*,void*);intMainintargcChar**argv) {        structSigaction Act;        Union Sigval Mysigval; inti; intSig;                 pid_t pid; Chardata[Ten]; memset (data,0,sizeof(data));  for(i=0; I <5; i++) Data[i]='2'; Mysigval.sival_ptr=data; Sig=atoi (argv[1]); PID=Getpid (); Sigemptyset (&act.sa_mask); Act.sa_sigaction=new_op;//three-parameter signal processing functionAct.sa_flags=sa_siginfo;//Information transfer switch, allow legend parameter information to New_op        if(Sigaction (Sig,&act,null) <0) {printf ("Install Sigal error\n"); }         while(1) {Sleep (2); printf ("wait for the signal\n"); Sigqueue (pid,sig,mysigval);//send a signal to this process and pass additional information        }}voidNew_op (intsignum,siginfo_t *info,void*myact)//realization of three-parameter signal processing function{        inti;  for(i=0;i<Ten; i++) {printf ("%c\n",(*( (Char*) ((*info). Si_ptr) +i))); } printf ("handle signal%d over;", Signum);}

In this example, the signal implements the transfer of additional information, and how the signal is processed depends on the specific application.

Core signal Processing & CPU8 Universal Registers

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: 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.