Lecture19
Lecture19
Signals
• A signal is a small message that notifies a process that an
event of some type has occurred in the system
• Sent from the OS kernel
• Could be requested by another process, by user, or automatically by
the kernel
• Signal type is identified by small integer ID’s (1-30)
2
Carnegie Mellon
Signals
• A signal is a small message that notifies a process that an
event of some type has occurred in the system
• Sent from the OS kernel
• Could be requested by another process, by user, or automatically by
the kernel
• Signal type is identified by small integer ID’s (1-30)
2
Carnegie Mellon
3
Carnegie Mellon
4
Carnegie Mellon
int main()
{
/* Install the SIGINT handler */
if (signal(SIGINT, sigint_handler) == SIG_ERR)
unix_error("signal error");
return 0;
} sigint.c
5
Carnegie Mellon
Time
6
Carnegie Mellon
7
Carnegie Mellon
Receiving/Responding to Signals
• Kernel handles signals delivered to a process p when it
switches to p from kernel mode to user mode (e.g.,
after a context switch)
Process A Process B
user code
user code
8
Carnegie Mellon
Receiving/Responding to Signals
• Kernel handles signals delivered to a process p when it
switches to p from kernel mode to user mode (e.g.,
after a context switch)
Process A Process B
9
Carnegie Mellon
10
Carnegie Mellon
10
Carnegie Mellon
10
Carnegie Mellon
Pending/Blocked Bits
• Kernel maintains pending and masked bit vectors in the
context of each process
• pending: represents the set of pending signals
• Kernel sets bit k in pending when a signal of type k is delivered
• Kernel clears bit k in pending when a signal of type k is received
• masked: represents the set of blocked signals
• Can be set and cleared by using the sigprocmask function
• Also referred to as the signal mask.
11
Carnegie Mellon
Receiving Signals
• Right before kernel is ready to pass control to process p
12
Carnegie Mellon
Receiving Signals
• Right before kernel is ready to pass control to process p
• Kernel computes the set of pending & nonmasked signals
for process p (PNM set)
12
Carnegie Mellon
Receiving Signals
• Right before kernel is ready to pass control to process p
• Kernel computes the set of pending & nonmasked signals
for process p (PNM set)
• If (PNM is empty), i.e., no signal is pending & nonmasked
12
Carnegie Mellon
Receiving Signals
• Right before kernel is ready to pass control to process p
• Kernel computes the set of pending & nonmasked signals
for process p (PNM set)
• If (PNM is empty), i.e., no signal is pending & nonmasked
• No signals to respond to; simply pass control to next instruction in the
logical flow for p
12
Carnegie Mellon
Receiving Signals
• Right before kernel is ready to pass control to process p
• Kernel computes the set of pending & nonmasked signals
for process p (PNM set)
• If (PNM is empty), i.e., no signal is pending & nonmasked
• No signals to respond to; simply pass control to next instruction in the
logical flow for p
• Else
12
Carnegie Mellon
Receiving Signals
• Right before kernel is ready to pass control to process p
• Kernel computes the set of pending & nonmasked signals
for process p (PNM set)
• If (PNM is empty), i.e., no signal is pending & nonmasked
• No signals to respond to; simply pass control to next instruction in the
logical flow for p
• Else
• Choose least nonzero bit k in pnm and force process p to receive
signal k, i.e., by executing the corresponding signal handler
12
Carnegie Mellon
Receiving Signals
• Right before kernel is ready to pass control to process p
• Kernel computes the set of pending & nonmasked signals
for process p (PNM set)
• If (PNM is empty), i.e., no signal is pending & nonmasked
• No signals to respond to; simply pass control to next instruction in the
logical flow for p
• Else
• Choose least nonzero bit k in pnm and force process p to receive
signal k, i.e., by executing the corresponding signal handler
• Repeat for all nonzero k in pnm
12
Carnegie Mellon
Receiving Signals
• Right before kernel is ready to pass control to process p
• Kernel computes the set of pending & nonmasked signals
for process p (PNM set)
• If (PNM is empty), i.e., no signal is pending & nonmasked
• No signals to respond to; simply pass control to next instruction in the
logical flow for p
• Else
• Choose least nonzero bit k in pnm and force process p to receive
signal k, i.e., by executing the corresponding signal handler
• Repeat for all nonzero k in pnm
• Pass control to next instruction in logical flow for p
12
Carnegie Mellon
Blocking Signals
sigset_t mask, prev_mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
14
Carnegie Mellon
if (x == 5)
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon
if (x == 5)
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon
if (x == 5)
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon
if (x == 5)
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon
15
Carnegie Mellon
exit(0);
}
16
Carnegie Mellon
17
Carnegie Mellon
17
Carnegie Mellon
17
Carnegie Mellon
First Attempt
void handler(int sig)
{
pid_t pid;
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
if ((pid = Fork()) == 0) { /* Child */
Execve("/bin/date", argv, NULL);
}
/* Add the child to the job list */
addjob(pid);
}
exit(0);
}
18
Carnegie Mellon
First Attempt
void handler(int sig)
{ The following can happen:
pid_t pid;
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
if ((pid = Fork()) == 0) { /* Child */
Execve("/bin/date", argv, NULL);
}
/* Add the child to the job list */
addjob(pid);
}
exit(0);
}
18
Carnegie Mellon
First Attempt
void handler(int sig)
{ The following can happen:
pid_t pid;
• The first child runs, and
while ((pid = wait(NULL)) > 0) { /* Reap child */
/* Delete the child from the job list */ terminates
deletejob(pid);
}
}
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
if ((pid = Fork()) == 0) { /* Child */
Execve("/bin/date", argv, NULL);
}
/* Add the child to the job list */
addjob(pid);
}
exit(0);
}
18
Carnegie Mellon
First Attempt
void handler(int sig)
{ The following can happen:
pid_t pid;
• The first child runs, and
while ((pid = wait(NULL)) > 0) { /* Reap child */
/* Delete the child from the job list */ terminates
deletejob(pid);
} • Kernel sends SIGCHLD
}
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
if ((pid = Fork()) == 0) { /* Child */
Execve("/bin/date", argv, NULL);
}
/* Add the child to the job list */
addjob(pid);
}
exit(0);
}
18
Carnegie Mellon
First Attempt
void handler(int sig)
{ The following can happen:
pid_t pid;
• The first child runs, and
while ((pid = wait(NULL)) > 0) { /* Reap child */
/* Delete the child from the job list */ terminates
deletejob(pid);
} • Kernel sends SIGCHLD
}
• Context switch to parent,
int main(int argc, char **argv)
{ which executes the SIGCHLD
int pid; handler before
Signal(SIGCHLD, handler); addjob(pid) is executed
initjobs(); /* Initialize the job list */
while (1) {
if ((pid = Fork()) == 0) { /* Child */
Execve("/bin/date", argv, NULL);
}
/* Add the child to the job list */
addjob(pid);
}
exit(0);
}
18
Carnegie Mellon
First Attempt
void handler(int sig)
{ The following can happen:
pid_t pid;
• The first child runs, and
while ((pid = wait(NULL)) > 0) { /* Reap child */
/* Delete the child from the job list */ terminates
deletejob(pid);
} • Kernel sends SIGCHLD
}
• Context switch to parent,
int main(int argc, char **argv)
{ which executes the SIGCHLD
int pid; handler before
Signal(SIGCHLD, handler); addjob(pid) is executed
initjobs(); /* Initialize the job list */
• The handler deletes the job,
while (1) {
if ((pid = Fork()) == 0) { /* Child */ which isn’t in the queue yet!
Execve("/bin/date", argv, NULL);
}
/* Add the child to the job list */
addjob(pid);
}
exit(0);
}
18
Carnegie Mellon
First Attempt
void handler(int sig)
{ The following can happen:
pid_t pid;
• The first child runs, and
while ((pid = wait(NULL)) > 0) { /* Reap child */
/* Delete the child from the job list */ terminates
deletejob(pid);
} • Kernel sends SIGCHLD
}
• Context switch to parent,
int main(int argc, char **argv)
{ which executes the SIGCHLD
int pid; handler before
Signal(SIGCHLD, handler); addjob(pid) is executed
initjobs(); /* Initialize the job list */
• The handler deletes the job,
while (1) {
if ((pid = Fork()) == 0) { /* Child */ which isn’t in the queue yet!
Execve("/bin/date", argv, NULL);
} • The parent process resumes
/* Add the child to the job list */
addjob(pid);
and adds a terminated child
} to job list
exit(0);
}
18
Carnegie Mellon
First Attempt
void handler(int sig)
{ Key in this example: creating a
pid_t pid;
child and adding its PID to the
while ((pid = wait(NULL)) > 0) { /* Reap child */
/* Delete the child from the job list */
job list must be an atomic unit:
deletejob(pid); either both happen or neither
}
} happen; there can’t be
int main(int argc, char **argv)
anything else that separates
{ the two.
int pid;
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
if ((pid = Fork()) == 0) { /* Child */
Execve("/bin/date", argv, NULL);
}
/* Add the child to the job list */
addjob(pid);
}
exit(0);
}
19
Carnegie Mellon
Second Attempt
void handler(int sig)
{
sigset_t mask_all, prev_all;
pid_t pid;
sigfillset(&mask_all);
while ((pid = wait(NULL)) > 0) {
sigprocmask(SIG_BLOCK, &mask_all, &prev_all);
deletejob(pid);
sigprocmask(SIG_SETMASK, &prev_all, NULL);
}
}
int main(int argc, char **argv)
{
int pid;
sigset_t mask_all, prev_all;
sigfillset(&mask_all);
signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
if ((pid = Fork()) == 0) {
Execve("/bin/date", argv, NULL);
}
sigprocmask(SIG_BLOCK, &mask_all, &prev_all);
addjob(pid);
sigprocmask(SIG_SETMASK, &prev_all, NULL);
}
exit(0);
}
20
Carnegie Mellon
Sigfillset(&mask_all);
Sigemptyset(&mask_one);
Sigaddset(&mask_one, SIGCHLD);
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
Sigprocmask(SIG_BLOCK, &mask_one, &prev_one); /* Block SIGCHLD */
if ((pid = Fork()) == 0) { /* Child process */
Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
Execve("/bin/date", argv, NULL);
}
addjob(pid); /* Add the child to the job list */
Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
}
exit(0);
}
21
Carnegie Mellon
Sigfillset(&mask_all);
Sigemptyset(&mask_one);
Sigaddset(&mask_one, SIGCHLD);
Signal(SIGCHLD, handler);
initjobs(); /* Initialize the job list */
while (1) {
Sigprocmask(SIG_BLOCK, &mask_one, &prev_one); /* Block SIGCHLD */
if ((pid = Fork()) == 0) { /* Child process */
Why this? Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
Execve("/bin/date", argv, NULL);
}
addjob(pid); /* Add the child to the job list */
Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
}
exit(0);
}
21
Carnegie Mellon
Today
• Signals: The Way to Communicate with Processes
• Interrupts and exceptions: how signals are triggered
22
Carnegie Mellon
Interrupts in a Processor
Processor
Interrupt
Signal Bus
Lines Chipset
oard
ork
disk
netw
keyb
23
Carnegie Mellon
24
Carnegie Mellon
• Examples:
• Timer interrupt
• Every few ms, an external timer chip triggers an interrupt
24
Carnegie Mellon
• Examples:
• Timer interrupt
• Every few ms, an external timer chip triggers an interrupt
• Used by the kernel to take back control from user programs
• I/O interrupt from external device
• Hitting Ctrl-C at the keyboard
• Arrival of a packet from a network
• Arrival of data from a disk
24
Carnegie Mellon
Code for
Interrupt handler 0
• k = index into interrupt
table
Interrupt
Code for
Table
Interrupt handler 1
0
1
• Interrupt table lives in
Code for memory. Its start address is
2
... Interrupt handler 2
stored in a special register
n-1 ...
Code for
• Handler k is called each
time interrupt k occurs
Interrupt handler n-1
25
Carnegie Mellon
26
Carnegie Mellon
26
Carnegie Mellon
26
Carnegie Mellon
27
Carnegie Mellon
Synchronous Exceptions
• Caused by events that occur as a result of executing an instruction:
28
Carnegie Mellon
Synchronous Exceptions
• Caused by events that occur as a result of executing an instruction:
• Traps
• Intentional
• Examples: system calls, breakpoint traps, special instructions
• Faults
28
Carnegie Mellon
Synchronous Exceptions
• Caused by events that occur as a result of executing an instruction:
• Traps
• Intentional
• Examples: system calls, breakpoint traps, special instructions
• Faults
• Unintentional but possibly recoverable
• Examples: page faults (recoverable), protection faults (the
infamous Segmentation Fault!) (unrecoverable in Linux), floating
point exceptions (unrecoverable in Linux)
• These exceptions will generate signals to processes
• Aborts
28
Carnegie Mellon
Synchronous Exceptions
• Caused by events that occur as a result of executing an instruction:
• Traps
• Intentional
• Examples: system calls, breakpoint traps, special instructions
• Faults
• Unintentional but possibly recoverable
• Examples: page faults (recoverable), protection faults (the
infamous Segmentation Fault!) (unrecoverable in Linux), floating
point exceptions (unrecoverable in Linux)
• These exceptions will generate signals to processes
• Aborts
• Unintentional and unrecoverable
• Examples: illegal instruction, parity error
• Aborts current program through a SIGABRT signal
28
Carnegie Mellon
29
Carnegie Mellon
29
Carnegie Mellon
29
Carnegie Mellon
Multiprocessing Illustration
Memory
Process 1 Process 2 Process N
Stack Stack Stack
Heap Heap Heap
Data Data Data
Code Code Code
CPU
Registers
30
Carnegie Mellon
Problem 1: Space
Memory
Process 1 Process 2 Process N
Stack Stack Stack
Heap Heap Heap
Data Data Data
Code Code Code
31
Carnegie Mellon
Problem 1: Space
Memory
Process 1 Process 2 Process N
Stack Stack Stack
Heap Heap Heap
Data Data Data
Code Code Code
• Space:
• Each process’s address space is huge (64-bit): can memory hold it
(16GB is just 34-bit)?
• 2^48 bytes is 256 TB
• There are multiple processes, increasing the storage requirement
further
31
Carnegie Mellon
Hard Disk/
CPU SSD
Main/Physical
Cache Memory Several
Registers (SRAM) (DRAM) TBs
(DFF)
Several GBs
~1 ns 1-10 ns
100 ns
~ 10 us
32
Carnegie Mellon
• Challange: who is moving data back and forth between the DRAM/main
memory/physical memory and the disk?
• Ideally should be managed by the OS, not the programmer.
Hard Disk/
CPU SSD
Main/Physical
Cache Memory Several
Registers (SRAM) (DRAM) TBs
(DFF)
Several GBs
~1 ns 1-10 ns
100 ns
~ 10 us
32
Carnegie Mellon
Problem 2: Security
• Different programs/processes will share the same physical memory
•Or even different uses. A CSUG machine is accessed by all students, but
there is one single physical memory!
• What if a malicious program steals/modifies data from your program?
• If the malicious program get the address of the memory that stores your
password, should it be able to access it? If not, how to prevent it?
• We need isolation.
Hard Disk/
CPU SSD
Main/Physical
Cache Memory Several
Registers (SRAM) (DRAM) TBs
(DFF)
Several GBs
33
Carnegie Mellon
base 1
Program 1 Program 1
bound 1
base 2
Program 2
bound 2
Program 2
Main/Physical
Memory Hard Disk/
SSD 34
Carnegie Mellon
128 MB
Program 2
Program 2
12 MB
Main/Physical
Memory Hard Disk/
SSD 35