Linux signal Practice (3)--Signal core representation

Source: Internet
Author: User
Tags sigint signal signal handler

The representation of the signal in the kernel

The processing action of the signal is called the signal recursion (Delivery), the signal from the generation to the state between the recursion, called signal Pending (Pending). A process can choose to block (block) a signal. When the blocked signal is generated, it remains in the pending state until the process has unblocked the signal and executes the recursive action.

Note that blocking and ignoring are different , as long as the signal is blocked will not be recursive, and ignoring is the optional after the recursion of a processing action. The signal's representation in the kernel can be seen as:

Figure-The sending process of the signal

Explanatory notes:

1) The function in thePCB Process Control block (task_struct) has a signal mask status word (block) and a signal pending status Word (pending) and whether the flag is ignored ;

2) Signal Shielding status word (block), 1 for blocking, 0 for non-blocking;

The Signal pending status word (pending) of 1 represents pending, 0 means the signal can be reached;

3) Send SIGINT to the process, the kernel first determine whether the signal screen state word is blocked, if blocking, the signal is pending status word (pending) corresponding BITS made 1; If the blocking is lifted, the signal pending status word (pending) corresponding bits made 0; signal can be reached.

4) block status word, pending status word is 64 bit (bit);

5) Theblock status Word user can read and write, pending status Word user can only, this is the signal design mechanism .

Think 1: The state word is 64bit, when programming, how to represent the state word that?

Think about how the 2:block status word information Gets or operates? What APIs?

Think about how the 3:pending status word information Gets or operates? What APIs?

See the answer;

Signal Set operation function (state Word representation)

#include <signal.h>int sigemptyset (sigset_t *set);//signal set clear 0; (64bit/8=8 bytes) int sigfillset (sigset_t *set); The signal set 64bit all to 1int Sigaddset (sigset_t *set, int signo); According to Signo, the corresponding position of the signal concentration is 1int sigdelset (sigset_t *set, int signo); According to Signo, the corresponding position of the signal concentration is 0int sigismember (const sigset_t *set, int signo);//Determine if Signo is in the signal set

Sigprocmask: Read/change signal mask status word (block)

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

Return Value: 0 if successful, or 1 if there is an error

READ: If the Oset is a non-null pointer, the current signal screen word of the read process is passed through the Oset parameter.

Change: If the set is a non-null pointer, change the signal mask word for the process, and the parameter how indicates how to change it. If both the Oset and the set are non-null pointers, the original signal shielding word is backed up into the oset, and the signal screen word is changed according to the set and how parameters. Assuming that the current signal mask is mask, the following table describes the optional values for the How parameter.

How:

Sigpending get signal Pending status Word (pending) information

#include <signal.h>int sigpending (sigset_t *set);

DESCRIPTION

Sigpending () returns the set of signals that is pending for delivery to the calling thread

(i.e., the signals which has been raised while blocked).

The mask of pending signals is returned in set.

/** Example 1: Adding a signal SIGINT to the signal screen Word press CTRL + C again at this point, the process also receives the SIGINT signal **/inline void Err_exit (std::string message); void Sighandler ( int signo); void Printsigset (const sigset_t &sigset); int main () {//Although the signal handler function is installed here, the process still receives no SIGINT signal if (signal (SIG    INT, sighandler) = = Sig_err) err_exit ("Signal error");    Add signal shielding Word: shielding SIGINT signal sigset_t AddSet;    Sigemptyset (&addset);    Sigaddset (&addset, SIGINT);    if (Sigprocmask (Sig_block, &addset, NULL) = =-1) err_exit ("Sigprocmask error");    Continuously print the current signal shielding character sigset_t Sigset;        while (true) {sigpending (&sigset);        Printsigset (Sigset);    Sleep (1);    }}inline void Err_exit (std::string message) {perror (Message.c_str ()); Exit (exit_failure);} void Sighandler (int signo) {cout << "catch a signal, number =" << signo << Endl;} void Printsigset (const sigset_t &sigset) {for (unsigned i = 1; i < NSIG; ++i) {if (Sigismember (&s    Igset, i)) Putchar (' 1 ');    else Putchar (' 0 '); } putchar (' \ n ');}
/** Example 2: The SIGINT signal continues to be masked on the basis of example 1, but if the process receives a sigquit signal, the mask of the SIGINT signal is lifted, Need 1. Install a sigquit snap function in the main function 2. Sighandler function Modification **/int Main () {if (Signal (SIGINT, sighandler) = = Sig_err) Err_exi    T ("Signal SIGINT error");    if (Signal (sigquit, sighandler) = = Sig_err) err_exit ("Signal sigquit error");    Add signal shielding Word: shielding SIGINT signal sigset_t AddSet;    Sigemptyset (&addset);    Sigaddset (&addset, SIGINT);    if (Sigprocmask (Sig_block, &addset, NULL) = =-1) err_exit ("Sigprocmask error");    Continuously print the current signal shielding character sigset_t Sigset;        while (true) {sigpending (&sigset);        Printsigset (Sigset);    Sleep (1);  }}void sighandler (int signo) {switch (signo) {case Sigint:cout << "Catch a signal SIGINT" <<        Endl    Break        Case Sigquit://If it is a sigquit signal, the shielding of the SIGINT signal is lifted sigset_t unblockset;        Sigemptyset (&unblockset);        Sigaddset (&unblockset, SIGINT); if (Sigprocmask (Sig_unblock, &uNblockset, NULL) = =-1) err_exit ("Sigprocmask unblock error");        else cout << "sigprocmask success" << Endl;    Break        Default:cerr << "Unknown signal" << Endl;    Break }}/** Continuous Press CTRL + C keyboard, although sent a plurality of SIGINT signals, but because the signal is not stable (queuing is not supported), so only one, such as */

Example: Switch to real-time signal sigrtmaxint main () {if (Signal (Sigrtmax, sighandler) = = Sig_err) err_exit ("Signal Sigrtmax error");    if (Signal (sigquit, sighandler) = = Sig_err) err_exit ("Signal sigquit error");    Add signal shielding Word: shielding Sigrtmax signal sigset_t addset;    Sigemptyset (&addset);    Sigaddset (&addset, Sigrtmax);    if (Sigprocmask (Sig_block, &addset, NULL) = =-1) err_exit ("Sigprocmask error");    Continuously print the current signal shielding character sigset_t Sigset;        while (true) {sigpending (&sigset);        Printsigset (Sigset);    Sleep (1);    }}void sighandler (int signo) {if (Signo = = Sigrtmax) cout << "Catch a signal Sigrtmax" << Endl;        else if (Signo = = sigquit) {sigset_t unblockset;        Sigemptyset (&unblockset);        Sigaddset (&unblockset, Sigrtmax);        if (Sigprocmask (Sig_unblock, &unblockset, NULL) = =-1) err_exit ("Sigprocmask UNBLOCK error"); else cout << "sigprocmask Success" <&Lt    Endl } else Cerr << "Unknown signal" << Endl;}

/** sends four consecutive sigrtmax to the process, the process is able to receive a **/

Comprehensive case

1) Create child process and parent process;

2) Register SIGINT non-real-time signal and sigrtmin real-time signal, and add these two signals to the process shielding signal Group;

3) Register user-defined signals;

4) The sub-process sends 5 non-real-time signals and sends 5 real-time signals;

5) The sub-process then sends the SIGUSR1 to unblock the sigint,sigtrmin signal.

6) Observe the difference between real-time and non-real-time signals

program example void onsigaction (int signalnumber, siginfo_t *siginfostruct, void *) {//Get received data int receivenumber = Siginfost    ruct->si_int;        If the SIGUSR1 signal is received, the Sigint,sigrtmin shield if (signalnumber = = SIGUSR1) {sigset_t unblockset is lifted;        Sigemptyset (&unblockset);        Sigaddset (&unblockset,sigint);        Sigaddset (&unblockset,sigrtmin);        Sigprocmask (Sig_unblock,&unblockset,null);        Value will be garbled!        cout << "Receive SIGUSR1, Value =" << receivenumber << Endl;    cout << "Unblock, Receive SIGUSR1" << Endl;  } else if (Signalnumber = = SIGINT) {cout << Receive SIGINT, Value = "<< receivenumber <<    Endl } else if (Signalnumber = = sigrtmin) {cout << Receive sigrtmin, Value = "<< Receivenumber <    < Endl;    }}int Main () {struct Sigaction act;    If you need to make the signal handler receive additional data,//the sa_flags position must be sa_siginfo act.sa_flags = Sa_siginfo; SiGemptyset (&act.sa_mask);    Act.sa_sigaction = onsigaction;    Register Signal Processing function if (sigaction (Sigint,&act,null) < 0) Err_exit ("Sigaction SIGINT");    if (Sigaction (Sigrtmin,&act,null) < 0) Err_exit ("Sigaction sigrtmin");    if (Sigaction (Sigusr1,&act,null) < 0) Err_exit ("Sigaction SIGUSR1");    Blocking the signal sigint,sigrtmin signal sigset_t blockSet;    Sigemptyset (&blockset);    Sigaddset (&blockset,sigint);    Sigaddset (&blockset,sigrtmin);    if (Sigprocmask (Sig_block,&blockset,null) < 0) err_exit ("Sigprocmask error");    pid_t pid = fork ();    if (PID = =-1) err_exit ("fork Error");        else if (PID = = 0) {Union sigval Value;        Value.sival_int = 200;            Send a non-reliable signal to the parent process five times with extra data (in fact only once) for (int i = 0; i < 5; ++i) {+ + Value.sival_int;        if (Sigqueue (Getppid (), sigint,value)! = 0) err_exit ("Sigqueue error"); }//sends a reliable signal to the parent process five times with additional data (final receiveFIVE times!!!)        Value.sival_int = 0;            for (int i = 0; i < 5; ++i) {+ + Value.sival_int;        if (Sigqueue (Getppid (), sigrtmin,value)! = 0) err_exit ("Sigqueue error");    }//sends a SIGUSR1 signal to the parent process, lifting the sigint,sigrtmin signal blocking Kill (Getppid (), SIGUSR1);    } while (true) {pause (); }}

Operation Result:

Actually, I just received a non-reliable signal sigint!

Linux signal Practice (3)--Signal core representation

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.