CS 444CS 544 Operating Systems Processes Threads 1312006

  • Slides: 51
Download presentation
CS 444/CS 544 Operating Systems Processes & Threads 1/31/2006 Prof. Searleman jets@clarkson. edu

CS 444/CS 544 Operating Systems Processes & Threads 1/31/2006 Prof. Searleman jets@clarkson. edu

Outline l l Processes and how they communicate and cooperate Introduction to Threads NOTE:

Outline l l Processes and how they communicate and cooperate Introduction to Threads NOTE: l Thursday’s class will be held in the ITL (Science Center 334) l New due date for Lab#1: Tuesday, Feb. 7 l Read: Chapter 4

Process creation Question: How many processes will be created by running the following code?

Process creation Question: How many processes will be created by running the following code? int main (int argc, char **argv) { fork(); }

Process hierarchy Running process: p 0 PCp 0 int main () { 1: fork();

Process hierarchy Running process: p 0 PCp 0 int main () { 1: fork(); 2: fork(); 3: } State: before p 0 executes statement 1

Process hierarchy p 0 p 1 PCp 0 PCp 1 int main () {

Process hierarchy p 0 p 1 PCp 0 PCp 1 int main () { 1: fork(); 2: fork(); 3: } State: after p 0 executes statement 1 Who will run next? Depends on the scheduler. Suppose it’s process p 1 (requires a context switch from p 0 to p 1)

Process hierarchy Running process: p 1 p 0 p 1 PCp 0 PCp 1

Process hierarchy Running process: p 1 p 0 p 1 PCp 0 PCp 1 int main () { 1: fork(); 2: fork(); 3: } State: before p 1 executes statement 2

Process hierarchy Running process: p 1 p 0 PCp 1 int main () {

Process hierarchy Running process: p 1 p 0 PCp 1 int main () { 1: fork(); 2: fork(); 3: } PCp 2 State: after p 1 executes statement 2 p 2 Suppose that process p 0 is selected to run next (requires a context switch from p 1 to p 0)

Process hierarchy Running process: p 0 p 1 PCp 0 p 3 PCp 1

Process hierarchy Running process: p 0 p 1 PCp 0 p 3 PCp 1 int main () { 1: fork(); 2: fork(); 3: } PCp 2 PCp 3 State: after p 0 executes statement 2 How many processes were created? Answer: 4 (NOTE: other execution sequences are possible. ) Question: what happens to the 4 processes?

Init process l l l In last stage of boot process, kernel creates a

Init process l l l In last stage of boot process, kernel creates a user level process, init Init is the parent (or grandparent…) of all other processes Init does various important housecleaning activities l l l checks and mounts the filesystems, sets hostname, timezones, etc. Init reads various “resource configuration files” (/etc/rc. conf, etc) and spawns off processes to provide various services In multi-user mode, init maintains processes for each terminal port (tty) l Usually runs getty which executes the login program

Foreground vs Background int main (int argc, char **argv){ while (1){ int child. Pid;

Foreground vs Background int main (int argc, char **argv){ while (1){ int child. Pid; char* cmd. Line = read. Command. Line(); if (user. Choose. Exit(cmd. Line)){ wait for all background jobs } child. Pid = fork(); if (child. Pid == 0){ set. STDOUT_STDIN_STDERR(cmd. Line); exec( get. Command(cmd. Line)); } else if (run. In. Foreground(cmd. Line)){ wait(child. Pid); } else { Record child. Pid In list of background jobs} } }

Redirecting I/O l Three default file streams in each process l l l Stdout,

Redirecting I/O l Three default file streams in each process l l l Stdout, stdin, stderr In a shell, child process may need a different stdout, stdin or stderr than the parent Before call exec l l If there is a “ < infile” then set stdin to the infile If there is a “> outfile” then set the stdout the outfile

Dup 2 //after fork, in the child if (command line contains < infile){ int

Dup 2 //after fork, in the child if (command line contains < infile){ int fd = open (infile. Name, O_RDONLY); if (fd == -1){ redirection failed } else { dup 2 (fd, STDIN_FILENO); } } //exec

Cooperating Processes l l Processes can run independently of each other or processes can

Cooperating Processes l l Processes can run independently of each other or processes can coordinate their activities with other processes To cooperate, processes must use OS facilities to communicate l l One example: parent process waits for child Many others l Files (You’ve Used) l Sockets (Networks) l Pipes (Like Sockets for local machine; Pair of files) l Signals (Today) l Shared Memory l Events l Remote Procedure Call

Signals l Processes can register to handle signals with the signal function l l

Signals l Processes can register to handle signals with the signal function l l Processes can send signals with the kill function l l l kill (pid, signum) System defined signals like SIGHUP (0), SIGKILL (9), SIGSEGV(11) l l void signal (int signum, void (*proc) (int)) In UNIX shell, try: “kill – 9 pid. Of. Victim. Process” Signals not used by system like SIGUSR 1 and SIGUSR 2 Note: sigsend/sigaction similar to kill/signal

Signals if (signal(SIGUSR 1, sig_handler) == SIG_ERR) fprintf(stderr, "Unable to create handler for SIGUSR

Signals if (signal(SIGUSR 1, sig_handler) == SIG_ERR) fprintf(stderr, "Unable to create handler for SIGUSR 1n"); if (signal(SIGUSR 2, sig_handler) == SIG_ERR) fprintf(stderr, "Unable to create handler for SIGUSR 2n"); parent. Pid = getpid(); fprintf(stdout, "Parent process has id %dn", parent. Pid); fprintf(stdout, "Parent process forks child. . . n"); child. Pid = fork(); if (child. Pid == 0){ do. Child(); } else { do. Parent(); }

do. Child void do. Child() { /* I am the child */ my. Pid

do. Child void do. Child() { /* I am the child */ my. Pid = getpid(); assert(my. Pid != parent. Pid); fprintf(stdout, "In child (id %d) , Child process has id %dn", my. Pid); /* send a SIG_USR 1 to the parent */ fprintf(stdout, "Child process (id %d) sending 1 st SIGUSR 1 to parent process (id %d)n", my. Pid, parent. Pid); err = kill(parent. Pid, SIGUSR 1); if (err){ fprintf(stderr, "Child process (id %d) is unable to send SIGUSR 1 signal to the parent process (id %d)n", my. Pid, parent. Pid); } }

do. Parent void do. Parent() { my. Pid = getpid(); assert(my. Pid == parent.

do. Parent void do. Parent() { my. Pid = getpid(); assert(my. Pid == parent. Pid); fprintf(stdout, "In parent (id %d) , child process has id %dn", my. Pid, child. Pid); fprintf(stdout, "Parent process (id %d) sending 1 st SIGUSR 2 to child process (id %d)n", my. Pid, child. Pid); err = kill(child. Pid, SIGUSR 2); if (err){ fprintf(stderr, "Parent process (id %d) is unable to send SIGUSR 2 signal to the child process (id %d)n", my. Pid, child. Pid); } }

sig. Handler static void sig_handler(int signo){ switch(signo){ case SIGUSR 1: /* incoming SIGUSR 1

sig. Handler static void sig_handler(int signo){ switch(signo){ case SIGUSR 1: /* incoming SIGUSR 1 signal */ handle. SIGUSR 1(); break; case SIGUSR 2: /*incoming SIGUSR 2 signal */ handle. SIGUSR 2(); break; case SIGTERM: /* incoming SIGTERM signal */ handle. SIGTERM(); break; } return; }

handle. SIGUSR 1 void handle. SIGUSR 1(){ num. SIGUSR 1 handled++; if (my. Pid

handle. SIGUSR 1 void handle. SIGUSR 1(){ num. SIGUSR 1 handled++; if (my. Pid == parent. Pid){ fprintf(stdout, "Process %d: Parent Received SIGUSR 1 %un", my. Pid, num. SIGUSR 1 handled); } else { fprintf(stdout, "Error: Process %d: Received SIGUSR 1, but I am not the parent!!n", my. Pid); exit(1); } #if RECEIVE_MORE_THAN_ONE_SIGNAL if (signal(SIGUSR 1, sig_handler) == SIG_ERR){ fprintf(stderr, "Unable to reset handler for SIGUSR 1n"); } #endif }

Windows Process Creation BOOL Create. Process( LPCTSTR lp. Application. Name, // name of executable

Windows Process Creation BOOL Create. Process( LPCTSTR lp. Application. Name, // name of executable module LPTSTR lp. Command. Line, // command line string LPSECURITY_ATTRIBUTES lp. Process. Attributes, // SD LPSECURITY_ATTRIBUTES lp. Thread. Attributes, // SD BOOL b. Inherit. Handles, // handle inheritance option DWORD dw. Creation. Flags, // creation flags LPVOID lp. Environment, // new environment block LPCTSTR lp. Current. Directory, // current directory name LPSTARTUPINFO lp. Startup. Info, // startup information LPPROCESS_INFORMATION lp. Process. Information // process information );

Windows vs Unix q Windows doesn’t maintain quiet the same relationship between parent and

Windows vs Unix q Windows doesn’t maintain quiet the same relationship between parent and child q q Later versions of Windows have concept of “job” to mirror UNIX notion of parent and children (process groups) Waiting for a process to complete? q q Waitfor. Single. Object to wait for completion Get. Exit. Code. Process ( will return STILL_ALIVE until process has terminated)

Sockets l l A socket is an end-point for communication over the network Create

Sockets l l A socket is an end-point for communication over the network Create a socket l int socket(int domain, int type, int protocol) l Type = SOCK_STREAM for TCP Read and write socket just like files Can be used for communication between two processes on same machine or over the network

Pipes l l Bi-directional data channel between two processes on the same machine Created

Pipes l l Bi-directional data channel between two processes on the same machine Created with: l l int pipe (int fildes[2]) Read and write like files

Remote Procedure Call (RPC)

Remote Procedure Call (RPC)

Processes: Summary l A process includes l l How to create a process l

Processes: Summary l A process includes l l How to create a process l l Address space (Code, Data, Heap, Stack) Register values (including the PC) Resources allocated to the process l Memory, open files, network connections Initializing the PCB and the address space (page tables) takes a significant amount of time Interprocess communication l l IPC is costly also Communication must go through OS (“OS has to guard any doors in the walls it builds around processes for their protection”)

Problem which needs > 1 independent sequential process? l Some problems are hard to

Problem which needs > 1 independent sequential process? l Some problems are hard to solve as a single sequential process; easier to express the solution as a collection of cooperating processes l l l Hard to write code to manage many different tasks all at once How would you write code for “make phone calls while making dinner while doing dishes while looking through the mail” Can’t be independent processes because share data (your brain) and share resources (the kitchen and the phone) Can’t do them sequentially because need to make progress on all tasks at once Easier to write “algorithm” for each and when there is a lull in one activity let the OS switch between them On a multiprocessor, exploit parallelism in problem

Example: Web Server l Web servers listen on an incoming socket for requests l

Example: Web Server l Web servers listen on an incoming socket for requests l l Once it receives a request, it ignore listening to the incoming socket while it services the request Must do both at once One solution: Create a child process to handle the request and allow the parent to return to listening for incoming requests Problem: This is inefficient because of the address space creation (and memory usage) and PCB initialization

Observation l There are similarities in the process that are spawned off to handle

Observation l There are similarities in the process that are spawned off to handle requests l l They share the same code, have the same privileges, share the same resources (html files to return, cgi script to run, database to search, etc. ) But there are differences l l Operating on different requests Each one will be in a different stage of the “handle request” algorithm

Idea l l Let these tasks share the address space, privileges and resources Give

Idea l l Let these tasks share the address space, privileges and resources Give each their own registers (like the PC), their own stack etc Process – unit of resource allocation (address space, privileges, resources) Thread – unit of execution (PC, stack, local variables)

Single-Threaded vs Multithreaded Processes

Single-Threaded vs Multithreaded Processes

Process vs Thread l l Each thread belongs to one process One process may

Process vs Thread l l Each thread belongs to one process One process may contain multiple threads Threads are logical unit of scheduling Processes are the logical unit of resource allocation

Address Space Map For Single -Threaded Process Biggest Virtual Address Stack (Space for local

Address Space Map For Single -Threaded Process Biggest Virtual Address Stack (Space for local variables etc. For each nested procedure call) Stack Pointer Heap (Space for memory dynamically allocated e. g. with malloc) Statically declared variables (Global variables) Code Ox 0000 (Text Segment) PC

Address Space Map For Multithreaded Process Biggest Virtual Address Thread 1 stack Thread 2

Address Space Map For Multithreaded Process Biggest Virtual Address Thread 1 stack Thread 2 stack SP (thread 1) SP (thread 2) Heap (Space for memory dynamically allocated e. g. with malloc) Statically declared variables (Global variables) Code Ox 0000 (Text Segment) PC (thread 2) PC (thread 1)

Kernel support for threads? l l Some OSes support the notion of multiple threads

Kernel support for threads? l l Some OSes support the notion of multiple threads per process and others do not Even if no “kernel threads” can build threads at user level l l Each “multi-threaded” program gets a single kernel in the process During its timeslice, it runs code from its various threads User-level thread package schedules threads on the kernel level process much like OS schedules processes on the CPU l SAT question? CPU is to OS is to processes like? l Kernel thread is to User-level thread package is to user threads User-level thread switch must be programmed in assembly (restore of values to registers, etc. )

User-level Threads

User-level Threads

User-level threads l How do user level thread packages avoid having one thread monopolize

User-level threads l How do user level thread packages avoid having one thread monopolize the processes time slice? l l Solution 1: Non-preemptive l l l Solve much like OS does Rely on each thread to periodically yield Yield would call the scheduling function of the library Solution 2: OS is to user level thread package like hardware is to OS l l Ask OS to deliver a periodic timer signal Use that to gain control and switch the running thread

Kernel vs User Threads l l One might think, kernel level threads are best

Kernel vs User Threads l l One might think, kernel level threads are best and only if kernel does not support threads user level threads In fact, user level threads can be much faster l l Thread creation , “Context switch” between threads, communication between threads all done at user level Procedure calls instead of system calls (verification of all user arguments, etc. ) in all these cases!

Problems with User-level threads l l OS does not have information about thread activity

Problems with User-level threads l l OS does not have information about thread activity and can make bad scheduling decisions Examples: l If thread blocks, whole process blocks l l Kernel threads can take overlap I/O and computation within a process! Kernel may schedule a process with all idle threads

Scheduler Activations l l If have kernel level thread support available then use kernel

Scheduler Activations l l If have kernel level thread support available then use kernel threads *and* user-level threads Each process requests a number of kernel threads to use for running user-level threads on Kernel promises to tell user-level before it blocks a kernel thread so user-level thread package can choose what to do with the remaining kernel level threads User level promises to tell kernel when it no longer needs a given kernel level thread

Thread Support l Pthreads is a user-level thread library l l l Can use

Thread Support l Pthreads is a user-level thread library l l l Can use multiple kernel threads to implement it on platforms that have kernel threads Java threads (extend Thread class) run by the Java Virtual Machine Kernel threads l l l Linux has kernel threads (each has its own task_struct) – created with clone system call Each user level thread maps to a single kernel thread (Windows 95/98/NT/2000/XP, OS/2) Many user level threads can map onto many kernel level threads like scheduler activations (Windows NT/2000 with Thread. Fiber package, Solaris 2)

Pthreads Interface l l POSIX threads, user-level library supported on most UNIX platforms Much

Pthreads Interface l l POSIX threads, user-level library supported on most UNIX platforms Much like the similarly named process functions l l l thread = pthread_create(procedure) pthread_exit pthread_wait(thread) Note: To use pthreads library, #include <pthread. h> compile with -lpthread

Pthreads Interface (con’t) l Pthreads support a variety of functions for thread synchronization/coordination l

Pthreads Interface (con’t) l Pthreads support a variety of functions for thread synchronization/coordination l l Used for coordination of threads (ITC ) – more on this soon! Examples: l l Condition Variables ( pthread_cond_wait, pthread_signal) Mutexes(pthread_mutex_lock, pthread_mutex_unlock)

Performance Comparison Processes Fork/Exit 251 Kernel Threads Pthread_create/ Pthread_join 94 User-level Threads Pthread_create/ Pthread_join

Performance Comparison Processes Fork/Exit 251 Kernel Threads Pthread_create/ Pthread_join 94 User-level Threads Pthread_create/ Pthread_join 4. 5 In microseconds, on a 700 MHz Pentium, Linux 2. 2. 16, Steve Gribble, 2001.

Windows Threads HANDLE Create. Thread( LPSECURITY_ATTRIBUTES lp. Thread. Attributes, DWORD dw. Stack. Size, LPTHREAD_START_ROUTINE

Windows Threads HANDLE Create. Thread( LPSECURITY_ATTRIBUTES lp. Thread. Attributes, DWORD dw. Stack. Size, LPTHREAD_START_ROUTINE lp. Start. Address, DWORD dw. Creation. Flags, LPVOID lp. Parameter, DWORD dw. Creation. Flags, LPDWORD lp. Thread. Id);

Windows Thread Synchronization l l Windows supports a variety of objects that can be

Windows Thread Synchronization l l Windows supports a variety of objects that can be used for thread synchronization Examples l l l Events (Create. Event, Set. Event, Reset. Event, Wait. For. Single. Object) Semaphores (Create. Semaphore, Release. Semaphore, Wait. For. Single. Object) Mutexes (Create. Mutex, Release. Mutex, Wait. For. Single. Object) Wait. For. Multiple. Object More on this when we talk about synchronization

Warning: Threads may be hazardous to your health l l One can argue (and

Warning: Threads may be hazardous to your health l l One can argue (and John Ousterhout did) that threads are a bad idea for most purposes Anything you can do with threads you can do with an event loop l l Remember “make phone calls while making dinner while doing dishes while looking through the mail” Ousterhout says thread programming to hard to get right

Outtakes l Processes that just share code but do not communicate l l Wasteful

Outtakes l Processes that just share code but do not communicate l l Wasteful to duplicate Other ways around this than threads

Example: User Interface l l Allow one thread to respond to user input while

Example: User Interface l l Allow one thread to respond to user input while another thread handles a long operation Assign one thread to print your document, while allowing you to continue editing

Benefits of Concurrency l Hide latency of blocking I/O without additional complexity l l

Benefits of Concurrency l Hide latency of blocking I/O without additional complexity l l Without concurrency l Block whole process l Manage complexity of asynchronous I/O (periodically checking to see if it is done so can finish processing) Ability to use multiple processors to accomplish the task Servers often use concurrency to work on multiple requests in parallel User Interfaces often designed to allow interface to be responsive to user input while servicing long operations

Thread pools l What they are and how they avoid thread creation overhead

Thread pools l What they are and how they avoid thread creation overhead

Experiment l l l Start up various processes under Windows (Word, IE, . .

Experiment l l l Start up various processes under Windows (Word, IE, . . ) How many processes are started? How many threads and of what priority?