CS 3214 Computer Systems Godmar Back Lecture 12. Announcements Exercise 6 coming up Project 3...

Post on 01-Jan-2016

220 views 3 download

transcript

CS 3214Computer Systems

Godmar Back

Lecture 12

Announcements

• Exercise 6 coming up• Project 3 milestone due Oct 8

CS 3214 Fall 2010

THREADS AND PROCESSESPart 1

CS 3214 Fall 2010

Processes

• Def: An instance of a program in execution• OS provides each process with key abstractions

– Logical control flow• 1 flow – single-threaded process• Multiple flows – multi-threaded process

– Private address space– Abstracted resources: e.g., stdout/stdin file descriptors

• These abstractions create the illusion that each process has access to its own– CPU (or CPUs for multi-threaded processes)– Memory– Devices: e.g., terminal

CS 3214 Fall 2010

Context Switching

• Historical motivation for processes was introduction of multi-programming: – Load multiple processes into memory, and switch to

another process if current process is (momentarily) blocked

– This required protection and isolation between these processes, implemented by a privileged kernel

• Time-sharing: switch to another process periodically to make sure all processes make equal progress

• Switch between processes is called a context switch

CS 3214 Fall 2010

CS 3214 Fall 2010

Dual-Mode Operation

• Two fundamental modes:– “kernel mode” – privileged

• aka system, supervisor or monitor mode • Intel calls its PL0, Privilege Level 0 on x86

– “user mode” – non-privileged• PL3 on x86

• Bit in CPU – controls operation of CPU– Privileged operations can only

be performed in kernel mode. Example: hlt

– Must carefully control transition between user & kernel mode

int main(){ asm(“hlt”);}

int main(){ asm(“hlt”);}

Mode Switching

• User Kernel mode– For reasons external or internal to CPU

• External (aka hardware) interrupt: – timer/clock chip, I/O device, network card, keyboard, mouse– asynchronous (with respect to the executing program)

• Internal interrupt (aka software interrupt, trap, or exception)– are synchronous– can be intended (“trap”): for system call (process wants to enter

kernel to obtain services)– or unintended (usually): (“fault/exception”) (division by zero, attempt

to execute privileged instruction in user mode, memory access violation, invalid instruction, alignment error, etc.)

• Kernel User mode switch on iret instruction

CS 3214 Fall 2010

CS 3214 Fall 2010

A Context Switch Scenario

Process 1

Process 2

Kernel

user mode

kernel mode

Timer interrupt: P1 is preempted, context switch to P2

Timer interrupt: P1 is preempted, context switch to P2

System call: (trap): P2 starts I/O operation, blocks context switch to process 1

System call: (trap): P2 starts I/O operation, blocks context switch to process 1

I/O device interrupt:P2’s I/O completeswitch back to P2

I/O device interrupt:P2’s I/O completeswitch back to P2

Timer interrupt: P2 still hastime left, no context switch

Timer interrupt: P2 still hastime left, no context switch

CS 3214 Fall 2010

Context Switching, Details

Process 1

Process 2

Kernel

user mode

kernel mode

intr_entry:(saves entire CPU state)(switches to kernel stack)

intr_entry:(saves entire CPU state)(switches to kernel stack) intr_exit:

(restore entire CPU state)(switch back to user stack)

iret

intr_exit:(restore entire CPU state)(switch back to user stack)

iret

switch_threads: (in)(saves caller’s state)

switch_threads: (in)(saves caller’s state)

switch_threads: (out)(restores caller’s state)

switch_threads: (out)(restores caller’s state)(kernel stack switch) (kernel stack switch)

CS 3214 Fall 2010

System Calls

Process 1

Kernel

user mode

kernel mode

User processes access kernel services by trapping into the kernel, executing kernel code to perform the service, then returning – very much like a library call. Unless the system call cannot complete immediately, this does not involve a context switch.

User processes access kernel services by trapping into the kernel, executing kernel code to perform the service, then returning – very much like a library call. Unless the system call cannot complete immediately, this does not involve a context switch.

Kernel’s System Call Implementation

Syscall example: write(2)

CS 3214 Fall 2010

/* gcc -static -O -g -Wall write.c -o write */ #include <unistd.h>

intmain(){ const char msg[] = "Hello, World\n"; return write(1, msg, sizeof msg);}

0805005a <__write_nocancel>: 805005a: 53 push %ebx 805005b: 8b 54 24 10 mov 0x10(%esp),%edx #arg2 805005f: 8b 4c 24 0c mov 0xc(%esp),%ecx # arg1 8050063: 8b 5c 24 08 mov 0x8(%esp),%ebx # arg0 8050067: b8 04 00 00 00 mov $0x4,%eax # syscall no 805006c: cd 80 int $0x80 805006e: 5b pop %ebx 805006f: 3d 01 f0 ff ff cmp $0xfffff001,%eax 8050074: 0f 83 56 1e 00 00 jae 8051ed0 <__syscall_error> 805007a: c3 ret

/usr/include/asm/unistd.h:….#define __NR_write 4….

CS 3214 Fall 2010

KernelThreads

Process 1

Process 2

Kernel

user mode

kernel mode

Most OS support kernel threads that never run in user mode – these threads typically perform bookkeeping or other supporting tasks. They do not service system calls or faults.

Most OS support kernel threads that never run in user mode – these threads typically perform bookkeeping or other supporting tasks. They do not service system calls or faults.

Kernel Thread

Careful: “kernel thread” not the same as kernel-level thread (KLT) – more on KLT later

Context vs Mode Switching

• Mode switch guarantees kernel gains control when needed– To react to external events– To handle error situations– Entry into kernel is controlled

• Not all mode switches lead to context switches– Kernel decides when – subject of scheduling policies

• Mode switch does not change the identity of current process/thread– See blue/yellow colors in slide on ctxt switch details

• Hardware knows about modes, does not (typically) know about contexts

CS 3214 Fall 2010

CS 3214 Fall 2010

Reasoning about Processes:Process States

• Only 1 process (per CPU) can be in RUNNING state

RUNNINGRUNNING

READYREADYBLOCKEDBLOCKED

Processmust waitfor event

Event arrived

Schedulerpicks process

Processpreempted

Process States

• RUNNING:– Process is on CPU, its instructions are executed

• READY:– Process could make progress if a CPU were available

• BLOCKED:– Process cannot make progress even if a CPU were available

because it’s waiting for something (e.g., a resource, a signal, a point in time, …)

• Model is simplified– OS have between 5 and 10 states typically

• Terminology not consistent across OS:– E.g., Linux calls BLOCKED “SLEEPING” and READY

“RUNNING”CS 3214 Fall 2010

User View

• If process’s lifetimes overlap, they are said to execute concurrently– Else they are sequential

• Default assumption is concurrently• Exact execution order is unpredictable

– Programmer should never make any assumptions about it

• Any interaction between processes must be carefully synchronized

CS 3214 Fall 2010

CS 3214 Fall 2010

Process Creation

• Two common paradigms:– Cloning vs. spawning

• Cloning: (Unix)– “fork()” clones current process– child process then loads new program

• Spawning: (Windows)– “exec()” spawns a new process with new program

• Difference is whether creation of new process also involves a change in program

CS 3214 Fall 2010

fork()#include <unistd.h>#include <stdio.h>

intmain(){ int x = 1;

if (fork() == 0) { // only child executes this printf("Child, x = %d\n", ++x); } else { // only parent executes this printf("Parent, x = %d\n", --x); }

// parent and child execute this printf("Exiting with x = %d\n", x);

return 0;}

#include <unistd.h>#include <stdio.h>

intmain(){ int x = 1;

if (fork() == 0) { // only child executes this printf("Child, x = %d\n", ++x); } else { // only parent executes this printf("Parent, x = %d\n", --x); }

// parent and child execute this printf("Exiting with x = %d\n", x);

return 0;}

Child, x = 2Exiting with x = 2Parent, x = 0Exiting with x = 0

CS 3214 Fall 2010

The fork()/join() paradigm

• After fork(), parent & child execute in parallel– Unlike a fork in the road, here we

take both roads• Used in many contexts• In Unix, ‘join()’ is called wait()• Purpose:

– Launch activity that can be done in parallel & wait for its completion

– Or simply: launch another program and wait for its completion (shell does that)

Parent:fork()

Parent:fork()

Parent:join()

Parent:join()

Parentprocessexecutes

Parentprocessexecutes

Childprocess executes

Childprocess executes

Childprocess

exits

Childprocess

exits

OS notifies

CS 3214 Fall 2010

fork()#include <sys/types.h>#include <unistd.h>#include <stdio.h>

int main(int ac, char *av[]) { pid_t child = fork(); if (child < 0) perror(“fork”), exit(-1); if (child != 0) { printf ("I'm the parent %d, my child is %d\n", getpid(), child); wait(NULL); /* wait for child (“join”) */ } else { printf ("I'm the child %d, my parent is %d\n", getpid(), getppid());

execl("/bin/echo", "echo", "Hello, World", NULL); }}

#include <sys/types.h>#include <unistd.h>#include <stdio.h>

int main(int ac, char *av[]) { pid_t child = fork(); if (child < 0) perror(“fork”), exit(-1); if (child != 0) { printf ("I'm the parent %d, my child is %d\n", getpid(), child); wait(NULL); /* wait for child (“join”) */ } else { printf ("I'm the child %d, my parent is %d\n", getpid(), getppid());

execl("/bin/echo", "echo", "Hello, World", NULL); }}

fork() vs. exec()

• fork():– Clone most state of parent, including memory– Inherit some state, e.g. file descriptors– Keeps program, changes process– Called once, returns twice

• exec():– Overlays current process with new executable– Keeps process, changes program– Called once, does not return (if successful)

CS 3214 Fall 2010

exit(3) vs. _exit(2)

• exit(3) destroys current processes• OS will free resources associated with it

– E.g., closes file descriptors, etc. etc.• Can have atexit() handlers

– _exit(2) skips them• Exit status is stored and can be retrieved by

parent– Single integer– Convention: exit(EXIT_SUCCESS) signals

successful execution, where EXIT_SUCCESS is 0CS 3214 Fall 2010

wait() vs waitpid()

• int wait(int *status)– Blocks until any child exits– If status != NULL, will contain value child

passed to exit()– Return value is the child pid– Can also tell if child was abnormally

terminated• int waitpid(pid_t pid, int *status, int options)

– Can say which child to wait forCS 3214 Fall 2010

If multiple children completed, will take in arbitrary order– Can use macros WIFEXITED and WEXITSTATUS to

get information about exit statusvoid fork10(){ pid_t pid[N]; int i; int child_status; for (i = 0; i < N; i++)

if ((pid[i] = fork()) == 0) exit(100+i); /* Child */

for (i = 0; i < N; i++) {pid_t wpid = wait(&child_status);if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\

n", wpid, WEXITSTATUS(child_status));

else printf("Child %d terminate abnormally\n", wpid);

}}

Wait Example

CS 3214 Fall 2010

Observations on fork/exit/wait• Process can have many children at any point in time• Establishes a parent/child relationship

– Resulting in a process tree• Zombies: processes that have exited, but their parent hasn’t

waited for them– “Reaping a child process” – call wait() so that zombie’s resources

can be destroyed• Orphans: processes that are still alive, but whose parent has

already exited (without waiting for them)– Become the child of a dedicated process (“init”) who will reap

them when they exit• “Run Away” processes: processes that (unintentionally)

execute an infinite loop and thus don’t call exit() or wait()CS 3214 Fall 2010