CMPSC 311 – Introduction to Systems Programming
Professors:
(Slides are mostly by Professor Patrick McDaniel and Professor Abutalib Aghayev)
Copyright By PowCoder代写 加微信 powcoder
CMPSC 311 – Introduction to Systems Programming
Control Flow
• Processors do only one thing:
• from startup to shutdown, a CPU simply reads and executes a sequence of
instructions, one at a time
• This sequence is the CPU’s control flow (or flow of control)
• If no SIGNUM is given, then SIGTERM is used by default.
$ ps -U mcdaniel
$ ./signals
Sleeping …zzzzz ….
Signal handler got a SIGHUP! Signals received : 1
Woken up!!
Sleeping …zzzzz ….
Signal handler got a SIGNINT! Signals received : 2
Woken up!!
Sleeping …zzzzz ….
57613 pts/4
$ kill -1 57613 $ kill -2 57613 $ kill -9 57613
00:00:00 signals
CMPSC 311 – Introduction to Systems Programming
SIGTERM vs. SIGKILL
• SIGTERM interrupts the program and asks it to shut down, which it should.
• Sometimes this does not work (for instance when the process is in a locked state)
• It is often desirable to add a signal handler to handle the SIGTERM, so that it can gracefully shut down the process, cleanup memory, close files, etc.
• SIGKILL kills the process
• Can lead to inconsistent state, because there is no opportunity to gracefully shutdown
the process.
Definition: the term graceful shutdown refers to the proper and complete sync with secondary storage, disposal of resources, and normal termination.
CMPSC 311 – Introduction to Systems Programming
• Killall is a program than sends signals to all instances of a particular progam. killall [-
• Where
• If no SIGNUM is given, then SIGTERM is used by default.
$ killall -1 signals
$ killall -2 signals
$ killall -SIGKILL signals
$ ./signals
Sleeping …zzzzz ….
Signal handler got a SIGHUP! Signals received : 1
Woken up!!
Sleeping …zzzzz ….
Signal handler got a SIGNINT! Signals received : 2
Woken up!!
Sleeping …zzzzz ….
CMPSC 311 – Introduction to Systems Programming
• raise allows a process to send signals to itself. int raise(int sig);
• There are a range of reasons why a process might want to do this. • Suspend itself (SIGSTOP)
• Kill itself (SIGKILL)
• Reset its configuation (SIGHUP)
• User defined signals (SIGUSR1..)
void suicide_signal(void) { raise(SIGKILL);
return; // This will never be reached }
CMPSC 311 – Introduction to Systems Programming
User-defined signal handlers
• You can create your own signal handlers simply by creating a function void
• and passing a function pointer to the function
sighandler_t signal(int signum, sighandler_t handler);
• Thereafter, whenever a signal of the type signo is raised. your program is called instead of the default handler.
void signal_handler(int no) {
printf(“Sig handler got a [%d]\n”, no); return;
signal(SIGHUP, signal_handler); signal(SIGINT, signal_handler);
CMPSC 311 – Introduction to Systems Programming
Function pointers
• A function pointer is a pointer to a function that can be assigned, passed as parameters, and called
• is the variable names
•
int myfunc(int i) {
printf(“Got into function with %d\n”, i);
int main( void ) { int (*func)(int); func = myfunc; func(7);
return 0; }
$ ./signals
Got into function with 7 $
CMPSC 311 – Introduction to Systems Programming
An alternate approach
• The sigaction() system call changes the action taken by a process on receipt of a specific signal.
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
• signnum – is the signal number to be handled
• act – is a structure containing information about the new handler, NULL means ignore the signal • oldact – is a pointer to the previously assigned handler, as assigned in call to function
struct sigaction new_action, old_action; new_action.sa_handler = signal_handler; new_action.sa_flags = SA_NODEFER | SA_ONSTACK; sigaction(SIGINT, &new_action, &old_action);
CMPSC 311 – Introduction to Systems Programming
Why another API?
• Many argue that the sigaction function is better:
• The signal() function does not block other signals from arriving while the current handler is executing; sigaction()
can block other signals until the current handler returns.
• The signal() function resets the signal action back to SIG_DFL (default) for almost all signals. • Better tuning of signals/controls of process through flags
• SA_NODEFER – don’t suspend signals while in handler
• SA_ONSTACK – provide alternate stack for signal handler
• SA_RESETHAND – Restore the signal action to the default upon entry to the signal handler.
Note: In general, sigaction is preferred over signal.
CMPSC 311 – Introduction to Systems Programming
Putting it all together …
void signal_handler(int no) { printf(”Signal received : %d\n”, no); if (no == SIGHUP) {
printf(“Signal handler got a SIGHUP!\n”); } else if (no == SIGINT) {
printf(“Signal handler got a SIGNINT!\n”); }
void cleanup_handler(int no) { printf(“Killed”);
int main(void) {
$ ./signals
Sleeping …zzzzz ….
Signal received : 1
Signal handler got a SIGHUP! Woken up!!
Sleeping …zzzzz ….
Signal received : 2
Signal handler got a SIGNINT! Woken up!!
Sleeping …zzzzz ….
struct sigaction new_action, old_action; // Setup the signal actions new_action.sa_handler = signal_handler;
new_action.sa_flags = SA_NODEFER | SA_ONSTACK;
sigaction( SIGINT, &new_action, &old_action );
signal( SIGHUP, signal_handler ); // Setup the signal handlers signal( SIGTERM, cleanup_handler );
while (1) {
printf( “Sleeping …zzzzz ….\n” ); select( 0, NULL, NULL, NULL, NULL ); printf( “Woken up!!\n” );
// Return successfully
return 0; }
CMPSC 311 – Introduction to Systems Programming
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com