The book "Advanced Programming in UNIX environments" comes with many small and exquisite programs. When I read this book, rewrite the code in the book according to your own understanding (most of them are on the copybook) to deepen your understanding (it's too difficult to read a book, huh, huh ). This example is successfully tested on ubuntu10.04.
Program Introduction: This example shows the correct method to protect critical zones from being interrupted by specific signals.
// Apue program 10-10: Print blocked words for processes // apue program 10-15: protect critical zones from signal interruption # include <unistd. h> # include <stdio. h> # include <stdlib. h> # include <signal. h> # include <errno. h> // output the error message and exit void error_quit (const char * Str) {fprintf (stderr, "% s \ n", STR); exit (1 );} // print the name of the signal in the blocked word for the call process dependency (test only the several types we use) void pr_mark (const char * Str) {sigset_t sigset; int error_save; error_save = errno; int temp = sigprocmask (0, null, & sigset); If (temp <0) E Rror_quit ("sigpromask error"); printf ("% s", STR); If (sigismember (& sigset, SIGINT) printf ("SIGINT "); if (sigismember (& sigset, sigquit) printf ("sigquit"); If (sigismember (& sigset, SIGUSR1) printf ("SIGUSR1 "); if (sigismember (& sigset, sigalrm) printf ("sigalrm"); printf ("\ n"); errno = error_save;} void sig_int (INT signo) {pr_mark ("\ Nin sig_int:");} int main (void) {sigset_t newmask, oldmask, waitmask; Pr _ Mark ("program start:"); // sets the processing function for the SIGINT signal if (sig_err = signal (SIGINT, sig_int) error_quit ("signal (SIGINT) error "); // initialize the waitmask signal set to an empty sigemptyset (& waitmask); // Add the SIGUSR1 signal sigaddset (& waitmask, SIGUSR1) in the waitmask Signal Set ); // initialize the newmask signal set to an empty sigemptyset (& newmask); // Add the SIGINT signal sigaddset (& newmask, SIGINT) in the newmask Signal Set ); // set oldmask to the current blocked Signal Set (to facilitate future recovery) // Add newmask Signal Set int temp = sigprocmask (sig_block, & Newmask, & oldmask); If (temp <0) error_quit ("sig_block error"); pr_mark ("in critical region:"); // this operation is hard to understand, see note 2 // enter the critical section and wait for the SIGINT signal temp = sigsuspend (& waitmask); If (temp! =-1) error_quit ("sigsuspend error"); // After receiving the SIGINT signal, exit the critical section pr_mark ("after return from sigsuspend :"); // recover the blocked signal set temp = sigprocmask (sig_setmask, & oldmask, null); If (temp <0) error_quit ("sig_setmask error"); pr_mark ("program Exit: "); Return 0 ;}
Running example (in red ):
Qch @ Ubuntu :~ /Code $ GCC temp. C-o temp
Qch @ Ubuntu :~ /Code $./temp
Program start:
In critical region: SIGINT
^ C
In sig_int: SIGINT SIGUSR1
After return from sigsuspend: SIGINT
Program Exit:
Note:
1: The critical section refers to a code segment (SIGUSR1) that does not want to be interrupted by a certain type of signal)
2: The entire atomic operation process of sigsuspend is:
(1) set a new mask to block the current process;
(2) receive the signal and restore the original mask;
(3) Call the signal processing function set by this process;
(4) After the signal processing function returns, sigsuspend returns.
3: sigsuspend and sigprocmask (); pause (); the difference is:
Sigsuspend integrates signal capturing and calling of signal processing functions, that is, it sets a new mask to block the current process. If there is a signal, I will receive the signal and call the signal processing function, the problem with sigprocmask (); pause (); is that it wants to receive signals after pause, instead of between sigprocmask () and pause.
PS: I am dizzy in this section, so the above may be wrong. If you find any mistakes, please make suggestions and learn and make progress together.