Saturday, October 11, 2014

Unix Prog: kill and raise functions

1. System Definitions:

 ubuntu@ip-172-31-23-227:~$ less /usr/include/signal.h  
 ......  
 /* Send signal SIG to process number PID. If PID is zero,  
   send SIG to all processes in the current process's process group.  
   If PID is < -1, send SIG to all processes in process group - PID. */  
 #ifdef __USE_POSIX  
 extern int kill (__pid_t __pid, int __sig) __THROW;  
 #endif /* Use POSIX. */  
 ......  
 /* Raise signal SIG, i.e., send SIG to yourself. */  
 extern int raise (int __sig) __THROW;  
 __END_NAMESPACE_STD  
 ......  

Note: the call "raise(signo)" equals "kill(getpid(), signo)"

For kill system call:
if(pid > 0): the signal is sent to the process whose process ID is pid
if(pid == 0): the signal is sent to all processes whose process group ID equals the process group ID of the sender and for which the sender has permission to send the signal
if(pid < 0): the signal is sent to all processes whose process group ID equals the absolute value of pid and for which the sender has permission to send the signal.
if(pid == -1): the signal is sent to all processes on the system for which the sender has permission to send the signal.

2. Permission
1) super user could use "kill" to send signal to any process in the system
2) normal user could use "kill" to send signal to some process if process's real/effective user id equals real/effective user id of the calling process.

Note: if the 2nd argument of kill system call is 0, then the kill system call will just check if a specific process still exists but no signal is sent. Also note that, when kill system returns, the process id may be recycled and original process already exited, so the return value is of limited usage.

It also guarantee that if the signal is not blocked on the receiver process side, the signal is then delivered before the kill returns.

3. Example:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<signal.h>  
   
 void sig_usr(int signo)  
 {  
  printf("received SIGUSR1 signal!\n");  
 }  
   
 int main(int argc, char* argv[])  
 {  
  if(signal(SIGUSR1, sig_usr) == SIG_ERR) {  
   printf("signal error!\n");  
   exit(1);  
  }  
   
  // Send signal to itself  
  if(kill(getpid(), SIGUSR1) < 0) {  
   printf("kill error!\n");  
   exit(2);  
  }  
   
  // Check if the process still exists  
  if(kill(getpid(), 0) < 0) {  
   printf("kill error! probably process doesn't exist!\n");  
   exit(2);  
  }  
   
  // Use raise system call to send signal to itself  
  if(raise(SIGUSR1) < 0) {  
   printf("raise error!\n");  
   exit(3);  
  }  
   
  exit(0);  
 }  

shell:
The program firstly setup the signal handler for signal SIGUSR1, then it calls "kill" system call to send this signal to itself, and then send NULL signal(0) to itself to check if itself still exists, and lastly it use raise system to send SIGUSR1 signal to itself again.
 ubuntu@ip-172-31-23-227:~$ ./killraise.out  
 received SIGUSR1 signal!  
 received SIGUSR1 signal!  

No comments:

Post a Comment