Top Banner
Operating Systems, 142 Practical Session 2, Signals and Assignment 1 1
48

Operating Systems , 142

Dec 31, 2015

Download

Documents

Operating Systems , 142. Practical Session 2, Signals and Assignment 1. Signals. Signals are a way of sending simple messages to processes/ threads. Used to notify a process of important events. Signals can be sent by other processes/ threads , or by the kernel. - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Operating Systems ,  142

Operating Systems, 142

Practical Session 2, Signals and Assignment 1

1

Page 2: Operating Systems ,  142

Signals

• Signals are a way of sending simple messages to processes/ threads.

• Used to notify a process of important events. • Signals can be sent by other processes/

threads, or by the kernel.• Signals are defined in POSIX.• Signals can be found in Linux but not in XV6,

you can add them yourself!

2

Page 3: Operating Systems ,  142

Reacting to Signals

• Signals are processed (by the kernel) after a process finished running in kernel mode, just before returning to user mode:– Upon returning from a system call.– Upon returning from a timer interrupt (interrupt

sent by the hardware clock).

3

Page 4: Operating Systems ,  142

Signals: Synchronous VS. Asynchronous

• Programs are synchronous: executed line by line• Signals can be synchronous or asynchronous

– Synchronous: occur as a direct result of the executing instruction stream. Examples: dividing by zero, segmentation fault, etc.

– Asynchronous: external to (and in some cases unrelated to) the current execution context. A mechanism for an inter-process communication. Example: receiving a termination signal from a different process.

4

Page 5: Operating Systems ,  142

Signals-Examples

• SIGSEGV – Segmentation Faults• SIGFPE – Floating Point Error• SIGSTOP – Causes process to suspend itself• SIGCONT – Causes a suspended process to resume

execution

Which are synchronous?

A list of signals in Linux: http://www.ucs.cam.ac.uk/docs/course-notes/unix-courses/Building/files/signals.pdf

5

Page 6: Operating Systems ,  142

Signal Table

• Each process has a signal table• Each signal has an entry in the table• Each signal has an indicator whether to ignore

the signal or not (SIG_IGN)• Each signal has a column of what to do upon

receiving the signal (if not ignoring it)

6

Handler SIG_IGN Sig_Num

1

2

Page 7: Operating Systems ,  142

Blocking and Ignoring

• Blocking: The signal is not delivered to the process. It remains pending until the block is removed.

• Ignoring: The signal is discarded by the kernel without any action being taken. The execution of the process continues even if non-meaningful (i.e. ignoring SIGFPE or SIGSEGV).

According to POSIX, the behavior of a process is undefined after it ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill or raise.

7

Page 8: Operating Systems ,  142

Signal Handlers

• Each signal has a default action. For example:– SIGTERM – Terminate process. – SIGFPE (floating point exception) – dump core and

exit.

• The default action can be changed by the process using the signal*/ sigaction system call.

It is highly recommended to refrain from using the signal call in your code, as we will see later. Nonetheless it is important to be familiar with it since it appears in many legacy programs.

8

Page 9: Operating Systems ,  142

Signal Handlers

• Five default actions: – Ignore: ignores the signal; no action taken.– Exit: forces the process to exit.– Core: forces the process to exit and create a core file.– Stop: stops the process.– Continue: resume execution of a stopped process.

Some functions are not safe to call from within a signal handler, such as printf, malloc, etc. A useful technique to overcome this is to use a signal handler to set a flag and then check that flag from the main program and print a message if required. Further reading: http://www.ibm.com/developerworks/linux/library/l-reent/index.html

9

Page 10: Operating Systems ,  142

Signal Handlers

• Two signals cannot be ignored or have their associated action changed:– SIGKILL– SIGSTOP

(Don’t confuse with SIGTSTP, which is sent when a user ^z in the shell. The default actions of both signals are similar, but the latter can be modified).

• When calling execvp() all signals are set to their default action. The bit that specifies whether to ignore the signal or not is preserved. Why?

10

Page 11: Operating Systems ,  142

Scheme of signal processing

11

User Mode Kernel Mode

Normal program flow

do_signal()handle_signal()

setup_frame()

Signal handler

Return code on the stack

system_call()sys_sigreturn()

restore_sigcontext()

An event which traps to kernel

Page 12: Operating Systems ,  142

Sending Signals

• Signals can be sent: – From the keyboard– From the command line via the shell– Using system calls

12

Page 13: Operating Systems ,  142

Keyboard Signals

• Ctrl–C – Sends a SIGINT signal . By default this causes the process to terminate.

• Ctrl-\ - Sends a SIGQUIT signal. Causes the process to terminate.

• Ctrl-Z – Sends a SIGTSTP signal. By default this causes the process to suspend execution.

Note: not all keyboard signals are supported in all shells.

13

Page 14: Operating Systems ,  142

Command line Signals

• kill <signal> <PID> – Sends the specified signal to the specified PID. A Negative PID specifies a whole process group.– Kill -9 <PID> sends a SIGKILL which terminates the process.

• killall <args> <commands> – can be used to send multiple signals to all processes running specific commands. – Example: killall -9 java

• fg – Resumes the execution of a suspended process (sends a SIGCONT).

14

Page 15: Operating Systems ,  142

System call Signals

Kill(pid_t pid,int sig)

Usage example:

#include <unistd.h> /* standard unix functions, like getpid() */#include <sys/types.h> /* various type definitions, like pid_t */#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); 15

Page 16: Operating Systems ,  142

Signal Priority

• Each pending signal is marked by a bit in a 32 bit word.• Therefore there can only be one signal pending of each type.• A process can’t know which signal came first.• The process executes the signals starting at the lowest

numbered signal.• POSIX 2001 also defines a set of Real-Time Signals which

behave differently:– Multiple instances may be queued– Provide richer information (may be accompanied by an integer)– Delivered in guaranteed order– Use SIGRTMIN+n up to SIGRTMAX to refer to these signals (32 in

Linux)

16

Page 17: Operating Systems ,  142

Manipulation of Signals

sighandler_t signal(int signum, sighandler_t handler)

• Registers a new signal handler for the signal with number signum.

• The signal handler is set to sighandler which may be a user specified function, or either SIG_IGN or SIG_DFL.

• If the corresponding handler is set to SIG_IGN or SIG_DFL, then the signal is ignored or set do default action accordingly.

• Return Value: previous value of the signal handler, or SIG_ERR on error.

• Deprecated, do not use!

17

Page 18: Operating Systems ,  142

Manipulation of Signals• On some systems (e.g. System V Unix), if the handler is set to a function

sighandler and a signal is received, then first the handler is reset to SIG_DFL, and next sighandler is called.

• This may result in portability issues, or unwanted signal handling.• One solution to this problem is demonstrated in the “ouch” signal handler

function:void ouch(int sig)

{

printf(“OUCH! - I got signal %d\n”, sig);

signal(SIGINT, ouch);

}

• What is the problem with this solution?

18

Page 19: Operating Systems ,  142

Manipulation of Signals- sigactionint sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

• A more sophisticated (and safe) way of manipulating signals. • Doesn’t restore (by default) the signal handler to default when

delivering a signal.• signum is the number of the signal.• act is a pointer to a struct containing much information including the

new signal handler.• oldact if not null will receive the old signal handler.

For more details and another example see:

http://www.opengroup.org/onlinepubs/009695399/functions/sigaction.html

19Example

Page 20: Operating Systems ,  142

Manipulation of Signals- sigactionThe sigaction structure is defined as something like:

struct sigaction { void (*sa_handler)(int); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };

• sa_handler specifies the action to be associated with signum and may be SIG_DFL, SIG_IGN, or a pointer to a signal handling function.

• sa_mask specifies a mask of signals which should be blocked during execution of the signal handler. In addition, the signal which triggered the handler will be blocked, unless the SA_NODEFER flag is used.

• sa_flags specifies a set of flags which modify the behavior of the signal.

20

Page 21: Operating Systems ,  142

Manipulation of Signals- sigprocmask

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

The sigprocmask call is used to change the list of currently blocked signals. The behaviour of the call is dependent on the value of how, as follows:

– SIG_BLOCK The set of blocked signals is the union of the current set and the set argument.

– SIG_UNBLOCK The signals in set are removed from the current set of blocked signals. It is legal to attempt to unblock a signal which is not blocked.

– SIG_SETMASK The set of blocked signals is set to the argument set.

21

Page 22: Operating Systems ,  142

Manipulation of Signals- sigprocmask

• sigset_t is a basic data structure used to represent a signal set.

• Initialization of sigset_t should be done using: sigemptyset, sigfillset, sigaddset, …

• A variable of type sigset_t should not be manipulated manually (for portability)!

• An example of usage can be found at: http://www.linuxprogrammingblog.com/code-examples/blocking-signals-with-sigprocmask

22

Example

Page 23: Operating Systems ,  142

Manipulation of Signals- sigpending

int sigpending(sigset_t *set);

Returns the set of signals that are pending for delivery to the calling thread (i.e., the signals which have been raised while blocked). The mask of pending signals is returned in set.

23

Page 24: Operating Systems ,  142

Waiting for signals

int pause(void);

Causes the calling process (or thread) to sleep until a (any) signal is delivered that either terminates the process or causes the invocation of a signal-catching function.

int sigsuspend(const sigset_t *mask);

Temporarily replaces the signal mask of the process, and suspends the process until a signal not belonging to the waiting mask arrives.Allows waiting for a particular signal.

24

Page 25: Operating Systems ,  142

The system call alarm

unsigned alarm(unsigned seconds);

Requests the system to generate a SIGALRM for the process after seconds time have elapsed. Processor scheduling delays may prevent the process from handling the signal as soon as it is generated.

• If seconds is 0, a pending alarm request, if any, is canceled.• Alarm requests are not stacked; only one SIGALRM generation

can be scheduled in this manner. If the SIGALRM signal has not yet been generated, the call shall result in rescheduling the time at which the SIGALRM signal is generated.

25

Page 26: Operating Systems ,  142

Example 1#include <stdio.h> /* standard I/O functions */#include <unistd.h> /* standard unix functions, like getpid() */#include <sys/types.h> /* various type definitions, like pid_t*/#include <signal.h> /* signal name macros, and the signal() prototype */

/* first, here is the signal handler */void catch_int(int sig_num){ /* reassign the signal handler again to catch_int, for next time */ signal(SIGINT, catch_int); /* and print the message */ printf("Don't do that\n");}int 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 */ while (true) { pause(); } }

Causes the process to halt execution until it receives any signal.

26

Page 27: Operating Systems ,  142

Example 2int cpid[5]; // holds the pids of the childrenint j; // index to cpid

// function to activate when a signal is caughtint sigCatcher() { signal(SIGINT, sigCatcher); // re-assign the signal catcher printf("PID %d caught one\n", getpid()); if(j > -1) kill(cpid[j], SIGINT); // send signal to next child in cpid}

27

Page 28: Operating Systems ,  142

Example 2-Continued

int main() { int i; int zombie; int status; int pid; signal(SIGINT, sigCatcher); // sets a handler for INT signal …

28

Page 29: Operating Systems ,  142

Example 2-Continuedfor(i=0; i<5; i++){ if((pid=fork()) == 0){ // create new child printf("PID %d ready\n", getpid()); j = i-1;

pause(); // wait for signal exit(0); // end process (become a zombie) } else // Only father updates the cpid array. cpid[i] = pid; } sleep(2); // allow children time to enter pausekill(cpid[4], SIGINT); // send signal to first childsleep(2); // wait for children to become zombies for(i=0; i<5; i++){ zombie = wait(&status); // collect zombies printf("%d is dead\n", zombie); } exit(0);}29

Page 30: Operating Systems ,  142

OutputPID 22899 ready PID 22900 ready PID 22901 ready PID 22902 ready PID 22903 ready PID 22903 caught one PID 22902 caught one PID 22901 caught one PID 22900 caught one PID 22899 caught one 22903 is dead 22901 is dead 22902 is dead 22899 is dead 22900 is dead

30

Page 31: Operating Systems ,  142

Security Issues

• Not all processes can send signals to all processes.

• Only the kernel and super user can send signals to all processes.

• Normal processes can only send signals to processes owned by the same user.

31

Page 32: Operating Systems ,  142

Process ID and Group ID• Each process has an ID (pid).• A process group is a collection of related processes.• Each process has a process-group identifier (pgid).• One process in the group is the group leader and all

member’s group ID is equal to the leaders pid. The group leader is the process group's initial member.

• A signal can be sent to a single process or to a process group.

• Used by the shell to control different tasks executed by it.

32

Page 33: Operating Systems ,  142

Process Group ID

int getpid() – return the process’s PID.int getpgrp() – return the process’s PGID.setpgrp() – set this process’s PGID to be equal to

his PID.setpgrp(int pid1, int pid2) – set process’s pid1

PGID to be equal to pid2’s PID.

33

Page 34: Operating Systems ,  142

MIDTERM QUESTION (APPENDIX)

34

Page 35: Operating Systems ,  142

Question from midterm 2004

תלמיד קיבל משימה לכתוב תכנית שמטרתה להריץ תכנית נתונההבינארי) הקובץ רק (ברשותו prompt-ב שימוש ע"י fork

. בנוסף נדרש התלמיד למנוע מן המשתמש "להרוג" את execvpו-הקשת ע"י התכנית ctrl-cהתכנית כי לב (שים prompt אינה

) my_prog.cמסתיימת לעולם). מצורף פתרון שהוצע ע"י התלמיד (.promptוכן התכנית

תאר במדויק את פלט התכנית כאשר הקלט הנו:א-

Good luck in the ^c midterm exam .

האם הפתרון המוצע עונה על הגדרת התרגיל?ב-

התכנית ג- את משנה היית כיצד לא, היא ל-ב' תשובתך אם my_prog.c לכל בקוד שתיים או שורה לשנות להוסיף/ (ניתן

היותר)?35

Page 36: Operating Systems ,  142

Question from midterm 2004#include…void cntl_c_handler(int dummy){

signal(SIGINT, cntl_c_handler);}

main (int argc, char **argv){int waited;int stat;argv[0] = “prompt”;signal (SIGINT, cntl_c_handler);if (fork() == 0) { // son

execvp(“prompt”,argv[0]);}else { // father

waited = wait(&stat);printf(“My son (%d) has terminated \n”,waited);

}}

my_prog.c

36

Page 37: Operating Systems ,  142

Question from midterm 2004

main(int argc, char** argv){char buf[20];while(1) {

printf(“Type something: “);gets(buf);printf(“\nYou typed: %s\n”,buf);

}}

prompt.c(זכרו כי קוד זה אינו ניתן לשינוי ע"י התלמיד)

37

Page 38: Operating Systems ,  142

Sample execution of code

הקלט א- כאשר התכנית פלט את במדויק תאר הנו:

Good luck in the ^c midterm exam.

Type something: Good luckYou typed: Good luckType something: in the ^cMy son 139 has terminated

38

Page 39: Operating Systems ,  142

Code is incorrect

האם הפתרון המוצע עונה על הגדרת התרגיל?

• Execvp doesn’t preserve signal handlers.• Therefore prompt.c doesn’t ignore ^c.• This means that the process can be

terminated.

39

Page 40: Operating Systems ,  142

Code correction

אם תשובתך ל-ב' היא לא, כיצד היית משנה את התכנית my_prog.c?(ניתן להוסיף/ לשנות שורה או שתיים בקוד לכל היותר)

1. Change signal (SIGINT, cntl_c_handler); in my_prog.c

With signal (SIGINT, SIG_IGN);

2. Add if (fork()==0){ signal (SIGINT, SIG_IGN); execvp(“prompt”,argv[0]);

40

Page 41: Operating Systems ,  142

Question from midterm 2012נתון קטע הקוד הבא:

void sigchld_handler(int s) {printf(“S”);

}int main(){

signal(SIGCHLD, sigchld_handler);signal_block(SIGCHLD);if (fork() != 0) {

printf(“A”);signal_unblock(SIGCHLD);printf(“B”);wait ();printf(“C”);

} else {

printf(“D”);}

}41

Page 42: Operating Systems ,  142

Question from midterm 2012

חוסמות signal_unblock וכן signal_blockידוע כי הפקודות •ומשחררות חסימה לסיגנלים.

שרטטו גרף מכוון המתאר את הפלטים האפשריים לקוד •זה. כל צומת בגרף תסמל הדפסה וכל קשת מכוונת תייצג

יחס סדר מתחייב בין הדפסות. וכי Z– ו X, Yלדוגמא, אם עפ"י קוד מסוים ידוע כי יודפסו •

Z (אך Y תופיע בהכרח לפני ההדפסה של Xההדפסה של יכול להופיע לפני או אחרי כל אחת מן ההדפסות

האחרות), יתקבל הגרף הבא:

42

X Y Z

Page 43: Operating Systems ,  142

Question from midterm 2012הגרף שיתקבל מהקוד:

void sigchld_handler(int s) {printf(“S”);

}int main(){

signal(SIGCHLD, sigchld_handler);signal_block(SIGCHLD);if (fork() != 0) {

printf(“A”);signal_unblock(SIGCHLD);printf(“B”);wait ();printf(“C”);

} else {

printf(“D”);}

}43

A

S

D

C

B

Page 44: Operating Systems ,  142

More Information• http://www.linuxjournal.com/article/3985• http://www.linux-security.cn/ebooks/ulk3-html/0596005652/understandlk-CHP-11.html• http://cs-pub.bu.edu/fac/richwest/cs591_w1/notes/wk3_pt2.PDF• http://books.google.com/books?id=9yIEji1UheIC&pg=PA156&lpg=PA156&dq=linux+ret_from

_intr()&source=bl&ots=JCjEvqiVM-&sig=z8CtaNgkFpa1MPQaCWjJuU5tq4g&hl=en&ei=zf3zSZsvjJOwBs-UxYkB&sa=X&oi=book_result&ct=result&resnum=22#PPA159,M1

• man signal, sigaction…• man kill…• Process groups:

http://www.win.tue.nl/~aeb/linux/lk/lk-10.htmlhttp://www.informit.com/articles/article.aspx?p=366888&seqNum=8

44

Page 45: Operating Systems ,  142

CODE EXAMPLES

45

Page 46: Operating Systems ,  142

sigaction code example

46

#include <signal.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <unistd.h>sig_atomic_t sigusr1_count = 0;void handler (int signal_number){

++sigusr1_count;}int main (int argc, char ** argv){

struct sigaction sa;memset (&sa, 0, sizeof (sa));sa.sa_handler = &handler;sigaction (SIGUSR1, &sa, NULL);/* Do some lengthy stuff here. *//* ... */printf (“SIGUSR1 was raised %d times\n”, sigusr1_count);return 0;

}

Back

Page 47: Operating Systems ,  142

sigprocmask code example/** This program blocks SIGTERM signal for 10 seconds using sigprocmask(2) * After that the signal is

unblocked and the queued signal is handled. */ #include <signal.h>#include <stdio.h>#include <string.h>#include <unistd.h>

static int got_signal = 0;

static void hdl (int sig) {got_signal = 1;

}

int main (int argc, char *argv[]) {sigset_t mask; sigset_t orig_mask; struct sigaction act;memset (&act, 0, sizeof(act));

act.sa_handler = hdl;47

Page 48: Operating Systems ,  142

sigprocmask code exampleif (sigaction(SIGTERM, &act, 0)) {

perror ("sigaction"); return 1;

} sigemptyset (&mask);sigaddset (&mask, SIGTERM); if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0) {

perror ("sigprocmask"); return 1;

} sleep (10); if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) {

perror ("sigprocmask"); return 1;

} sleep (1); if (got_signal) puts ("Got signal"); return 0; }

48 Back