Linux system programming 50 signals-sigsuspend() Set the state of the signal set and suspend atomic operations

NAME
       sigsuspend, rt_sigsuspend - wait for a signal


SYNOPSIS
       #include <signal.h>

       int sigsuspend(const sigset_t *mask);

Function: The following three steps are atomic operations

Step 1: Set the current process signal set state to the target signal set state mask, and save the process's old signal set state as oldmask

Step 2: Immediately enter the waiting signal phase

Step 3: Set the current process signal set state to the old signal set state oldmask after waking up after receiving the signal.


Experiment 1, implemented with pause(), after printing a line*, stop waiting for the signal and the driver continues to run

pause() Sleep waiting for signal to wake up, CTRL+C wakes up the program to execute and print the next line

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>


void sig_handler(int s)
{
	write(1,"!",1);
}

int main()
{
	int i,j;
	sigset_t set,saveset;

	signal(SIGINT,sig_handler);
	
	sigemptyset(&set); 
	sigaddset(&set,SIGINT); 

	
	sigprocmask(SIG_UNBLOCK,&set,&saveset);

	for(j=0;j < 1000;j++)
	{

		sigprocmask(SIG_BLOCK,&set,NULL); 
		for(i=0 ; i<5 ; i++) 
		{
			write(1,"*",1);
			sleep(1);
		}	
		write(1,"\n",1);
		sigprocmask(SIG_UNBLOCK,&set,NULL); 
 pause();
	}

	sigprocmask(SIG_SETMASK,&saveset,NULL);

	exit(0);
}


mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ ./a.out 
*****
^C!*****
^C!*****
^C!****^C*
!^\Quit (core dumped)
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ 

Question: It
is true that the program can be tentatively set after printing a line, wait for SIGINT and then print the next line*.
However, it is found that if the SIGINT signal is sent during the printing of the current line, the program will not be driven to print the next line of data. This is because

in

sigprocmask(SIG_UNBLOCK,&set,NULL); In the
middle of the two functions of pause() , when the signal blocking is released, before the pause() is executed, the SIGINT signal is responded to, so the signal does not work on pause(). That is, the process will not be awakened. After the program responds to the SIGINT signal, print! Then execute to pause(). We know that the program can be understood as being interrupted all the time while running, and the time slice has been repeatedly exhausted, that is, it repeatedly enters the kernel mode and waits for scheduling, and then continues to execute the program, so it is just right to switch from the kernel mode at this time Go back to the user mode and find the SIGINT signal, so immediately respond to the signal action. Our original intention is to immediately pause () after the execution of unblocking, and finally the SIGINT signal is applied to pause() to print the next line,
so the cause of this problem is sigprocmask(SIG_UNBLOCK,&set,NULL) and pause(). The combination of two operations is a non-atomic operation, it is not atomic.

Modification: implemented with sigsuspend()

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>


void sig_handler(int s)
{
	write(1,"!",1);
}

int main()
{
	int i,j;
	sigset_t set,saveset,oset;

	signal(SIGINT,sig_handler);
	
	sigemptyset(&set); 
	sigaddset(&set,SIGINT); 

	
	sigprocmask(SIG_UNBLOCK,&set,&saveset);

	sigprocmask(SIG_BLOCK,&set,&oset); 
	for(j=0;j < 1000;j++)
	{

		
		for(i=0 ; i<5 ; i++) 
		{
			write(1,"*",1);
			sleep(1);
		}	
		write(1,"\n",1);
		
		sigsuspend(&oset);
	}

	sigprocmask(SIG_SETMASK,&saveset,NULL);

	exit(0);
}


mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ gcc sigsuspend.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ ./a.out 
*****
^C!*****
^C!**^C*^C^C**
!*****
^C!**^\Quit (core dumped)
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ 

The target function can be achieved.

Guess you like

Origin blog.csdn.net/LinuxArmbiggod/article/details/114124505