Sunday, November 6, 2011

Communication using Signals in C programming

In the last chapter we used fork( ) and exec( ) library function to create a child process and to execute a new program respectively. These library functions got the job done by communication with the Linux OS. Thus the direction of communication was from the program to the OS. The reverse communication—from the OS to the program—is achieved using a mechanism called ‘Signal’. Let us now write a simple program that would help you experience the signal mechanism.

int main( )
{
while ( 1 )
printf ( "Pogram Running\n" ) ;
return 0 ;
}

The program is fairly straightforward. All that we have done here is we have used an infinite while loop to print the message "Program Running" on the screen. When the program is running we can terminate it by pressing the Ctrl + C. When we press Ctrl + C the keyboard device driver informs the Linux kernel about pressing of this special key combination. The kernel reacts to this by sending a signal to our program. Since we have done nothing to handle this signal the default signal handler gets called. In this default signal handler there is code to terminate the program. Hence on pressing Ctrl + C the program gets terminated.

But how on earth would the default signal handler get called. Well, it is simple. There are several signals that can be sent to a program. A unique number is associated with each signal. To avoid remembering these numbers, they have been defined as macros like SIGINT, SIGKILL, SIGCONT, etc. in the file ‘signal.h’. Every process contains several ‘signal ID - function pointer’ pairs indicating for which signal which function should be called. If we do not decide to handle a signal then against that signal ID the address of the default signal handler function is present. It is precisely this default signal handler for SIGINT that got called when we pressed Ctrl + C when the above program was executed. INT in SIGINT stands for interrupt.

Let us know see how can we prevent the termination of our program even after hitting Ctrl + C. This is shown in the following program:

# include <signal.h>
void sighandler ( int signum )
{
printf ( "SIGINT received. Inside sighandler\n" ) ;
}
int main( )
{
signal ( SIGINT, ( void* ) sighandler ) ;
while ( 1 )
printf ( "Program Running\n" ) ;
return 0 ;
}

In this program we have registered a signal handler for the SIGINT signal by using the signal( ) library function. The first parameter

of this function specifies the ID of the signal that we wish to register. The second parameter is the address of a function that should get called whenever the signal is received by our program. This address has to be typecasted to a void * before passing it to the signal( ) function.
Now when we press Ctrl + C the registered handler, namely, sighandler( ) would get called. This function would display the message ‘SIGINT received. Inside sighandler’ and return the control back to main( ). Note that unlike the default handler, our handler does not terminate the execution of our program. So only way to terminate it is to kill the running process from a different terminal. For this we need to open a new instance of command prompt (terminal). How to start a new instace of command prompt is discussed in Appendix H. Next do a ps –a to obtain the list of processes running at all the command prompts that we have launched. Note down the process id of a.out. Finally kill ‘a.out’ process by saying

# kill 3276

In my case the terminal on which I executed a.out was tty1 and its process id turned out to be 3276. In your case the terminal name and the process id might be a different number.

If we wish we can abort the execution of the program in the signal handler itself by using the exit ( 0 ) beyond the printf( ).

Note that signals work asynchronously. That is, when a signal is received no matter what our program is doing, the signal handler would immediately get called. Once the execution of the signal handler is over the execution of the program is resumed from the point where it left off when the signal was received.

No comments:

Post a Comment