suspend.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
volatile sig_atomic_t quitflag;
void sig_int(int signo)
{
if(signo == SIGINT) {
printf("\ninterrupt\n");
}
else if (signo == SIGQUIT) {
quitflag = 1;
}
}
int main(int argc, char* argv[])
{
sigset_t newmask, oldmask, zeromask;
// Setup signal handlers
if(signal(SIGINT, sig_int) == SIG_ERR) {
printf("signal(SIGINT) error");
exit(1);
}
if(signal(SIGQUIT, sig_int) == SIG_ERR) {
printf("signal(SIGQUIT) error");
exit(1);
}
// Make the signal set
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
// Block the SIGQUIT
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
printf("SIG_BLOCK error");
exit(2);
}
// Suspend while blocking nothing, waiting for SIGQUIT
while(quitflag == 0)
sigsuspend(&zeromask);
quitflag = 0;
// Restore the signal mask
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
printf("SIG_SETMASK error");
exit(2);
}
exit(0);
}
shell:
Everytime user input Ctrl C to trigger SIGINT, quitflag is keeping 0, and sigsuspend is still working. Only if user input the Ctrl \ to trigger the SIGQUIT, it will change the global variable quitflag to be 1, and stop running sigsuspend.
ubuntu@ip-172-31-23-227:~$ ./suspend.out
^C
interrupt
^C
interrupt
^\ubuntu@ip-172-31-23-227:~$
2. synchronization between parent and child process
sync.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
volatile sig_atomic_t sigflag;
sigset_t newmask, oldmask, zeromask;
void sig_usr(int signo)
{
sigflag = 1;
}
void TELL_WAIT(void)
{
// Setup the signal handler
if(signal(SIGUSR1, sig_usr) == SIG_ERR) {
printf("signal error!\n");
exit(1);
}
if(signal(SIGUSR2, sig_usr) == SIG_ERR) {
printf("signal error!\n");
exit(1);
}
// Make signal mask
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
sigaddset(&newmask, SIGUSR2);
// Block the SIGUSR1, SIGUSR2
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
printf("sigprocmask error!\n");
exit(2);
}
// Note: this function is used to initialize the synchronization infrastructure
}
void TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2);
}
void WAIT_PARENT(void)
{
// Child process wait for the SIGUSR1 from parent
while(sigflag == 0)
sigsuspend(&zeromask);
sigflag = 0;
// After receiving the SIGUSR1 from parent, restore signals
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
printf("sigprocmask error!\n");
exit(1);
}
}
void TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1);
}
void WAIT_CHILD(void)
{
// Parent process wait for the SIGUSR2 from child
while(sigflag == 0)
sigsuspend(&zeromask);
sigflag = 0;
// After receiving the SIGUSR2 from child, restore signals.
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
printf("sigprocmask error!\n");
exit(1);
}
}
int main(int argc, char* argv[])
{
// Firstly call TELL_WAIT to initialize the synchronization in parent and child processes
// Then call TELL_* function, while another process is blocked by WAIT_* function
}
No comments:
Post a Comment