signal.h - s3.amazonaws.com

Download Report

Transcript signal.h - s3.amazonaws.com

Operating Systems
IPC Unix Case Study: Signals
Signal: An IPC Mechanism
• With pipes we communicated data
• With signal, we can communicate control command
• The only information is:
– The number identifying the signal
• Interrupts a process and forces it to handle the event
immediately
• kill –l can be used to view all the signals supported by
your system
Sending signals to process
• From keyboard
– Ctrl-C, Ctrl-Z etc
• From the command line
– kill -<signal> <PID>
– fg
• Using the kill() system call
• Also used by the kill and fg command
#include <signal.h>
/* signal name macros, and the kill() prototype */
/* first, find my own process ID */
pid_t my_pid = getpid();
/*now that i got my PID, send myself the STOP
signal.*/
kill(my_pid, SIGSTOP);
Actions Performed upon Receiving
a Signal
There are three ways in which a process can
respond to a signal:
1. Explicitly ignore the signal.
2. Execute the default action associated with the
signal.
3. Catch the signal by invoking a corresponding
signal-handler function.
Signal Handler
•
•
•
•
Corresponding to each signal is a signal handler
Called when a process receives a signal
The function is called “asynchronously”
When the signal handler returns the process
continues, as if it was never interrupted
• Signal are different from interrupts as:
– Interrupts are sent to OS by H/W
– Signals are sent to a process by the OS, or by other
processes
– Note that signals have nothing to do with software
interrupts, which are still sent by the hardware (the CPU
itself, in this case).
The signal() System Call
• Used to set signal handler for a signal type
Example
void main()
{ /* set the INT (Ctrl-C) signal handler to 'catch_int' */
signal(SIGINT, catch_int);
/* now, lets get into an infinite loop of doing nothing. */
for ( ;; )
pause();
}
/* first, here is the signal handler */
void catch_int(int sig_num)
{ /* re-set the signal handler again to catch_int, for next time
*/
signal(SIGINT, catch_int);
/* and print the message */
printf("Don't do that");
}
Signal Handlers
• Pre-defined Signal Handlers
• SIG_IGN:
– Causes the process to ignore the specified signal.
– To ignore Ctrl-C completely
• signal(SIGINT, SIG_IGN);
• SIG_DFL:
– Causes the system to set the default signal handler for the
given signal
• signal(SIGTSTP, SIG_DFL);
Race conditions
• The occurrence of a second signal while the signal
handler function executes
• Might be of a different type then the one being handled
• Or even of the same type
sigprocmask()
• Allows us to specify a set of signals to block
• Returns the list of signals that were previously blocked
• int sigprocmask(int how, const sigset_t
*set, sigset_t *oldset);
sigprocmask()
• int how
– SIG_BLOCK
• Add set to the set of currently blocked signals
– SIG_UNBLOCK
• The signals in set are removed from the current set of blocked
signals.
– SIG_SETMASK
• The set of blocked signals is set to the argument set.
• const sigset_t *set
– The set of signals to be blocked, or to be added to the current mask, or
removed from the current mask (depending on the 'how' parameter).
• sigset_t *oldset
– If this parameter is not NULL, then it'll contain the previous mask.
– Can be used later restore back the situation, before sigprocmask() was
called.
Signal functions
• Define a new mask set
sigset_t mask_set;
• Clear the set (i.e. make it contain no signal numbers)
sigemptyset(&mask_set);
• Add a signal
sigaddset(&mask_set, SIGTSTP);
• Remove the TSTP signal from the set
sigdelset(&mask_set, SIGTSTP);
• Check if the TSTP signal is defined in our set
if (sigismember(&mask_set, SIGINT)
printf("signal INT is in our set\n");
else
printf("signal INT is not in our set - how
strange...\n");
• Make the set contain ALL signals available on the
system sigfillset(&mask_set)
Count_CTRL_C.c
#include <stdio.h> /* standard I/O functions
*/
#include <unistd.h> /* standard unix functions, like getpid()*/
#include <signal.h> /* signal name macros, and the signal() prototype */
/* first, define the Ctrl-C counter, initialize it with zero. */
int
ctrl_c_count = 0;
#define CTRL_C_THRESHOLD 5
int main(int argc, char* argv[])
{
/* set the Ctrl-C and Ctrl-Z signal handlers */
signal(SIGINT, catch_int);
signal(SIGTSTP, catch_suspend);
/* enter an infinite loop of waiting for signals */
for ( ;; )
pause();
return 0;
}
/* the Ctrl-C signal handler */
void catch_int(int sig_num)
{
sigset_t mask_set; /* used to set a signal masking set. */
sigset_t old_set;
/* used to store the old mask set. */
/* mask any further signals while we're inside the handler. */
sigfillset(&mask_set);
sigprocmask(SIG_SETMASK, &mask_set, &old_set);
/* increase count, and check if threshold was reached */
ctrl_c_count++;
if (ctrl_c_count >= CTRL_C_THRESHOLD)
{
char answer[30];
/* prompt the user to tell us if to really exit or not */
printf("\nRealy Exit? [y/N]: ");
fflush(stdout);
gets(answer);
if (answer[0] == 'y' || answer[0] == 'Y')
{
printf("\nExiting...\n");
fflush(stdout);
exit(0);
}
else
{
printf("\nContinuing\n");
fflush(stdout);
/* reset Ctrl-C counter */
ctrl_c_count = 0;
}
}
/* restore the old signal mask */
sigprocmask(SIG_SETMASK, &old_set, NULL);
}
/* the Ctrl-Z signal handler */
void catch_suspend(int sig_num)
{
sigset_t mask_set;
/* used to set a signal masking set. */
sigset_t old_set; /* used to store the old mask set. */
/* mask any further signals while we're inside the handler. */
sigfillset(&mask_set);
sigprocmask(SIG_SETMASK, &mask_set, &old_set);
/* print the current Ctrl-C counter */
printf("\n\nSo far, '%d' Ctrl-C presses were counted\n\n",
ctrl_c_count);
fflush(stdout);
/* restore the old signal mask */
sigprocmask(SIG_SETMASK, &old_set, NULL);
}
Implementing Timers Using Signals
• alarm : set a process alarm clock
• #include <unistd.h>
• unsigned alarm(unsigned sec);
• Sends the signal SIGALRM to the calling
process after the sec number of seconds have
elapsed
• If sec is 0, any previously made alarm request is
canceled.
• use-alarms_c.c
#include <signal.h> /* signal name macros, and the signal() prototype */
char user[40]; /* buffer to read user name from the user */
int main(int argc, char* argv[])
{
/* set a signal handler for ALRM signals */
signal(SIGALRM, catch_alarm);
/* prompt the user for input */
printf("Username: ");
fflush(stdout);
/* start a 30 seconds alarm */
alarm(30);
/* wait for user input */
gets(user);
/* remove the timer, now that we've got the user's input */
alarm(0);
printf("User name: '%s'\n", user);
}`
/* define an alarm signal handler. */
void catch_alarm(int sig_num)
{
printf("Operation timed out. Exiting...\n\n");
exit(0);
}