0% found this document useful (0 votes)
6 views

Lecture19

Uploaded by

minulo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Lecture19

Uploaded by

minulo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 71

CSC 252/452: Computer Organization

Fall 2024: Lecture 19

Instructor: Yanan Guo

Department of Computer Science


University of Rochester
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

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)

ID Name Default Action Corresponding Event


2 SIGINT Terminate User typed ctrl-c
9 SIGKILL Terminate Kill program (cannot override or ignore)
11 SIGSEGV Terminate Segmentation violation
14 SIGALRM Terminate Timer signal
17 SIGCHLD Ignore Child stopped or terminated

2
Carnegie Mellon

Default Actions to Signals


• Each signal type has a predefined default action, which is
one of:
• The process terminates
• The process stops until restarted by a SIGCONT signal
• The process ignores the signal

3
Carnegie Mellon

Installing Signal Handlers


• The signal function modifies the default action associated
with the receipt of signal signum:
• handler_t *signal(int signum, handler_t *handler)

• Different values for handler:


• SIG_IGN: ignore signals of type signum
• SIG_DFL: revert to the default action on receipt of signals of type signum
• Otherwise, handler is the address of a user-level function (signal handler)
• Called when process receives signal of type signum
• Referred to as “installing” the handler
• Executing handler is called “catching” or “handling” the signal
• When the handler executes its return statement, control passes
back to instruction in the control flow of the process that was
interrupted by receipt of the signal

4
Carnegie Mellon

Signal Handling Example


void sigint_handler(int sig) /* SIGINT handler */
{
printf("So you think you can stop the bomb with ctrl-c, do you?\n");
sleep(2);
printf("Well...");
fflush(stdout);
sleep(1);
printf("OK. :-)\n");
exit(0);
}

int main()
{
/* Install the SIGINT handler */
if (signal(SIGINT, sigint_handler) == SIG_ERR)
unix_error("signal error");

/* Wait for the receipt of a signal */


pause();

return 0;
} sigint.c
5
Carnegie Mellon

Signals Handlers as Concurrent Flows


• A signal handler is a separate logical flow (not process)
that runs concurrently with the main program

Process A Process A Process B

while (1) handler(){


; …
}

Time

6
Carnegie Mellon

Nested Signal Handlers


• Handlers can be interrupted by other handlers
Main program Handler S Handler T

(2) Control passes


(1) Program Icurr to handler S
catches signal s (4) Control passes
(3) Program to handler T
(7) Main program Inext catches signal t
resumes
(5) Handler T
(6) Handler S
returns to
returns to
handler S
main program

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

kernel code context switch


Time user code

kernel code context switch

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

Signal delivered Icurr user code (main)


to process A kernel code context switch

user code (main)

kernel code context switch


Signal received
user code (handler)
by process A
kernel code
Inext
user code (main)

9
Carnegie Mellon

Pending and Blocked Signals


• A signal is pending if sent but not yet received
• There can be at most one pending signal of any particular type for a
process
• That is: Signals are not queued
• If a process has a pending signal of type k, then subsequent
signals of type k that are sent to that process are discarded
• A pending signal is received at most once

10
Carnegie Mellon

Pending and Blocked Signals


• A signal is pending if sent but not yet received
• There can be at most one pending signal of any particular type for a
process
• That is: Signals are not queued
• If a process has a pending signal of type k, then subsequent
signals of type k that are sent to that process are discarded
• A pending signal is received at most once

• A process can block/mask the receipt of certain signals

10
Carnegie Mellon

Pending and Blocked Signals


• A signal is pending if sent but not yet received
• There can be at most one pending signal of any particular type for a
process
• That is: Signals are not queued
• If a process has a pending signal of type k, then subsequent
signals of type k that are sent to that process are discarded
• A pending signal is received at most once

• A process can block/mask the receipt of certain signals


• Blocked signals can be delivered, i.e., in the pending state, but will not
be received/responded to until the signal is unblocked

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);

/* Block SIGINT and save previous blocked set */


sigprocmask(SIG_BLOCK, &mask, &prev_mask);

/* Code region that will not be interrupted by SIGINT */

/* Restore previous blocked set, unblocking SIGINT */


sigprocmask(SIG_SETMASK, &prev_mask, NULL);

• Explicit blocking and unblocking signal


• sigprocmask function
• sigemptyset – Create empty set
• sigfillset – Add every signal number to set
• sigaddset – Add signal number to set
• sigdelset – Delete signal number from set
13
Carnegie Mellon

Safe Signal Handling


• Handlers are tricky because they are concurrent with main
program and may share the same global data structures.

14
Carnegie Mellon

Safe Signal Handling


• Handlers are tricky because they are concurrent with main
program and may share the same global data structures.
static int x = 5;
void handler(int sig)
{
x = 10;
}

int main(int argc, char **argv)


{
int pid, y = 0;
Signal(SIGCHLD, handler);

if ((pid = Fork()) == 0) { /* Child */


Execve("/bin/date", argv, NULL);
}

if (x == 5)
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon

Safe Signal Handling


• Handlers are tricky because they are concurrent with main
program and may share the same global data structures.
static int x = 5; What if the following happens:
void handler(int sig)
{
x = 10;
}

int main(int argc, char **argv)


{
int pid, y = 0;
Signal(SIGCHLD, handler);

if ((pid = Fork()) == 0) { /* Child */


Execve("/bin/date", argv, NULL);
}

if (x == 5)
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon

Safe Signal Handling


• Handlers are tricky because they are concurrent with main
program and may share the same global data structures.
static int x = 5; What if the following happens:
void handler(int sig)
{ • Parent process executes and
x = 10;
} finishes if (x == 5)

int main(int argc, char **argv)


{
int pid, y = 0;
Signal(SIGCHLD, handler);

if ((pid = Fork()) == 0) { /* Child */


Execve("/bin/date", argv, NULL);
}

if (x == 5)
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon

Safe Signal Handling


• Handlers are tricky because they are concurrent with main
program and may share the same global data structures.
static int x = 5; What if the following happens:
void handler(int sig)
{ • Parent process executes and
x = 10;
} finishes if (x == 5)

int main(int argc, char **argv) • Context switch to child,


{ which then terminates, sends
int pid, y = 0;
Signal(SIGCHLD, handler);
a SIGCHLD signal

if ((pid = Fork()) == 0) { /* Child */


Execve("/bin/date", argv, NULL);
}

if (x == 5)
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon

Safe Signal Handling


• Handlers are tricky because they are concurrent with main
program and may share the same global data structures.
static int x = 5; What if the following happens:
void handler(int sig)
{ • Parent process executes and
x = 10;
} finishes if (x == 5)

int main(int argc, char **argv) • Context switch to child,


{ which then terminates, sends
int pid, y = 0;
Signal(SIGCHLD, handler);
a SIGCHLD signal

if ((pid = Fork()) == 0) { /* Child */


• Another context switch back
Execve("/bin/date", argv, NULL); to parent, and now the kernel
} needs to execute the
if (x == 5)
SIGCHLD handler
y = x * 2; // You’d expect y == 10
exit(0);
}
14
Carnegie Mellon

Safe Signal Handling


• Handlers are tricky because they are concurrent with main
program and may share the same global data structures.
static int x = 5; What if the following happens:
void handler(int sig)
{ • Parent process executes and
x = 10;
} finishes if (x == 5)

int main(int argc, char **argv) • Context switch to child,


{ which then terminates, sends
int pid, y = 0;
Signal(SIGCHLD, handler);
a SIGCHLD signal

if ((pid = Fork()) == 0) { /* Child */


• Another context switch back
Execve("/bin/date", argv, NULL); to parent, and now the kernel
} needs to execute the
if (x == 5)
SIGCHLD handler
y = x * 2; // You’d expect y == 10
exit(0);
• When return to parent
} process, y == 20!
14
Carnegie Mellon

Safe Signal Handling


• Handlers are tricky because they are concurrent with main
program and may share the same global data structures.
• Programmers have no control over the execution ordering between the
main program and the signal handler, that is:
• when a signal happens/delivers (depends on user or other process)
• when the signal handler will be executed (depends on kernel)
• If not careful, shared data structures can be corrupted

15
Carnegie Mellon

Fixing the Signal Handling Bug


static int x = 5;
void handler(int sig)
{ • Block all signals before
x = 10; accessing a shared,
}
global data structure.
int main(int argc, char **argv)
{
int pid;
sigset_t mask_all, prev_all;
sigfillset(&mask_all);
signal(SIGCHLD, handler);

if ((pid = Fork()) == 0) { /* Child */


Execve("/bin/date", argv, NULL);
}

Sigprocmask(SIG_BLOCK, &mask_all, &prev_all);


if (x == 5)
y = x * 2; // You’d expect y == 10
Sigprocmask(SIG_SETMASK, &prev_all, NULL);

exit(0);
}
16
Carnegie Mellon

Another Unsafe Signal Handler Example

17
Carnegie Mellon

Another Unsafe Signal Handler Example


• Assume a program wants to do the following:
• The parent creates multiple child processes
• When each child process is created, add the child PID to a
queue
• When a child process terminates, the parent process
removes the child PID from the queue

17
Carnegie Mellon

Another Unsafe Signal Handler Example


• Assume a program wants to do the following:
• The parent creates multiple child processes
• When each child process is created, add the child PID to a
queue
• When a child process terminates, the parent process
removes the child PID from the queue
• One possible implementation:
• An array for keeping the child PIDs
• Use a loop to fork child, and add PID to the array after fork
• Install a handler for SIGCHLD in parent process
• The SIGCHLD handler removes the child PID

17
Carnegie Mellon

First Attempt
void handler(int sig)
{
pid_t pid;

while ((pid = wait(NULL)) > 0) { /* Reap child */


/* Delete the child from the job list */
deletejob(pid);
}
}

int main(int argc, char **argv)


{
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);
}

18
Carnegie Mellon

First Attempt
void handler(int sig)
{ The following can happen:
pid_t pid;

while ((pid = wait(NULL)) > 0) { /* Reap child */


/* Delete the child from the job list */
deletejob(pid);
}
}

int main(int argc, char **argv)


{
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);
}

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);
}
}

int main(int argc, char **argv)


{
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);
}

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
}

int main(int argc, char **argv)


{
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);
}

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

Third Attempt (The Correct One)


int main(int argc, char **argv)
{
int pid;
sigset_t mask_all, mask_one, prev_one;

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

Third Attempt (The Correct One)


int main(int argc, char **argv)
{
int pid;
sigset_t mask_all, mask_one, prev_one;

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

Interrupts, a.k.a., Asynchronous Exceptions


• Caused by events external to the processor
• Events that can happen at any time. Computers have little control.
• Indicated by setting the processor’s interrupt pin
• Handler returns to “next” instruction

24
Carnegie Mellon

Interrupts, a.k.a., Asynchronous Exceptions


• Caused by events external to the processor
• Events that can happen at any time. Computers have little control.
• Indicated by setting the processor’s interrupt pin
• Handler returns to “next” instruction

• Examples:
• Timer interrupt
• Every few ms, an external timer chip triggers an interrupt

24
Carnegie Mellon

Interrupts, a.k.a., Asynchronous Exceptions


• Caused by events external to the processor
• Events that can happen at any time. Computers have little control.
• Indicated by setting the processor’s interrupt pin
• Handler returns to “next” instruction

• 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

Each Interrupt Has a Handler


Interrupt • Each type of event has a
numbers unique interrupt number k

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

Sending Signals from the Keyboard


• Can you guess how Ctrl + C might be implemented?

26
Carnegie Mellon

Sending Signals from the Keyboard


• Can you guess how Ctrl + C might be implemented?
• Ctrl + C sends a keyboard interrupt to the CPU, which triggers an
interrupt handler

26
Carnegie Mellon

Sending Signals from the Keyboard


• Can you guess how Ctrl + C might be implemented?
• Ctrl + C sends a keyboard interrupt to the CPU, which triggers an
interrupt handler
• The interrupt handler, executed by the kernel, triggers certain piece of
the kernel, which generates the signal, which is then delivered to the
target process

26
Carnegie Mellon

When to Execute the Handler?


• Interrupts: when convenient. Typically wait until the current
instructions in the pipeline are finished
• Maskable verses Unmaskable
• Interrupts can be individually masked (i.e., ignored by CPU)
• Synchronous exceptions are usually unmaskable

• Some interrupts are intentionally unmaskable


• Called non-maskable interrupts (NMI)
• Indicating a critical error has occurred, and that the system is
probably about to crash

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

Where Do You Restart?


• Interrupts/Traps
• Handler returns to the following instruction

29
Carnegie Mellon

Where Do You Restart?


• Interrupts/Traps
• Handler returns to the following instruction
• Faults
• Exception handler returns to the instruction that caused the
exception, i.e., re-execute it!

29
Carnegie Mellon

Where Do You Restart?


• Interrupts/Traps
• Handler returns to the following instruction
• Faults
• Exception handler returns to the instruction that caused the
exception, i.e., re-execute it!
• Aborts
• Never returns to the program

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

Recall: Memory Hierarchy


• Solution: store all the data in disk (several TBs typically), and
use memory only for most recently used data
• Of course if a process uses all its address space that won’t be enough, but usually a
process won’t use all 64 bits. So it’s OK.

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

Recall: Memory Hierarchy


• Solution: store all the data in disk (several TBs typically), and
use memory only for most recently used data
• Of course if a process uses all its address space that won’t be enough, but usually a
process won’t use all 64 bits. So it’s OK.

• 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

One Way to Isolate: Segments


• Different processes will have exclusive access to just one part of the
physical memory.
• This is called Segments.
• Need a base register and a bound register for each process. Not
widely used today. x86 still supports it (backward compatibility!)
• Fast but not inflexible. Makes benign sharing hard.

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

Problem 3: Fragmentation (with Segments)


• Each process gets a continuous chunk of memory. Inflexible.
• What if a process requests more space than any continuous chunk in
memory but smaller than the total free memory?
• This is called “fragmentation”; will talk about this more later.

• Need to allow assigning discontinuous chunks of memory to


processes.
12 MB
Program 1 Program 1

128 MB

Program 2
Program 2
12 MB
Main/Physical
Memory Hard Disk/
SSD 35

You might also like