Sunday, October 19, 2014

Unix Prog: sigsuspend function(2)

1. sigsuspend Example:

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