What is a shell? The Unix shell (simplified) while(! EOF) An interpreter read input Runs programs on behalf of the user handle regular expressions int pid = fork() / / create child Allows programmer to create/manage set of programs if (pid == 0) { / / child here sh Original Unix shell (Bourne, 1977) exec(“program”, argc, argv0,...); csh BSD Unix C shell (tcsh enhances it) } bash “Bourne again” shell else { / / parent here Every command typed in the shell starts a child process ... of the shell } Runs at user-level. Uses syscalls: fork, exec, etc. Signals (Virtualized Interrupts) Sending a Signal Just Asynchronous notifications in user space Kernel delivers a signal to a destination a taste… process, for a variety of reasons Default ID Name Corresponding Event Action kernel detected a system event (e.g., division by zero (SIGFPE) or termination of Interrupt 2 SIGINT Terminate (e.g., CTRL-C from keyboard) a child (SIGCHLD) or… Kill program a process invoked the kill systems call 9 SIGKILL Terminate (cannot override or ignore) requesting kernel to send another process a signal 14 SIGALRM Terminate Timer signal debugging 17 SIGCHLD Ignore Child stopped or terminated suspension resumption Stop until Stop signal from terminal 20 SIGSTP SIGCONT (e.g., CTRL-Z from keyboard) timer expiration
Receiving a Signal int main() { pid_t pid[N]; int i, child_status; Signal for (i = 0; i < N; i++) / / N forks Each signal prompts one of these default actions if ((pid[i] = fork()) == 0) { while(1); / / child infinite loop Example terminate the process } ignore the signal /* Parent terminates the child processes */ for (i = 0; i < N; i++) { / / parent continues executing terminate the process and dump core printf("Killing proc. %d\n", pid[i]); kill(pid[i], SIGINT); stop the process } continue process if stopped /* Parent reaps terminated children */ for (i = 0; i < N; i++) { Signal can be caught by executing a user-level pid_t wpid = wait(&child_status); if (WIFEXITED(child_status)) / / parent checks for each child’ s exit - normal exit returns 1 function called signal handler printf("Child %d terminated w/ exit status %d\n", wpid, WEXITSTATUS(child_status)); similar to exception handler invoked in response to an else asynchronous interrupt printf("Child %d terminated abnormally\n", wpid); } Process can also be suspended waiting for a signal to exit(0); } be caught (synchronously) void int_handler(int sig) { Booting an OS Kernel printf("Process %d received signal %d\n", getpid(), sig); exit(0); } int main() { Handler pid_t pid[N]; int i, child_status; signal(SIGINT, int_handler) / / register handler for SIGINT for (i = 0; i < N; i++) / / N forks Bootloader Bootloader Example if ((pid[i] = fork()) == 0) { OS Kernel while(1); / / child infinite loop Login app } /* Parent terminates the child processes */ for (i = 0; i < N; i++) { / / parent continues executing printf("Killing proc. %d\n", pid[i]); kill(pid[i], SIGINT); } BIOS /* Parent reaps terminated children */ for (i = 0; i < N; i++) { pid_t wpid = wait(&child_status); Basic Input/Output System if (WIFEXITED(child_status)) / / parent checks for each child’ s exit printf("Child %d terminated w/ exit status %d\n", wpid, In ROM; includes the first instructions WEXITSTATUS(child_status)); else fetched and executed printf("Child %d terminated abnormally\n", wpid); } BIOS copies Bootloader, checking its cryptographic hash exit(0); 1 to make sure it has not been tampered with }
Booting an OS Kernel Booting an OS Kernel Bootloader Bootloader OS Kernel OS Kernel OS Kernel Login app Login app BIOS BIOS OS Kernel Bootloader Bootloader Bootloader copies OS Kernel, Bootloader copies OS Kernel, 2 2 checking its cryptographic hash checking its cryptographic hash Booting an OS Kernel Booting an OS Kernel Bootloader Bootloader OS Kernel OS Kernel Login app Login app Login app BIOS BIOS Bootloader OS Kernel Bootloader OS Kernel Kernel initializes its data structures 3 4 Kernel: Copies first process from disk (devices, interrupt vector table, etc)
Booting an OS Kernel Bootloader OS Kernel Threads Login app An abstraction for concurrency (Chapters 25-27) BIOS OS Kernel Login app Bootloader 4 Kernel: Copies first process from disk Changes PC and sets mode bit to 1 And the dance begins! 113 Threads: a New Abstraction Rethinking the Process Abstraction for Concurrency A single-execution stream of instructions that represents Processes serve two key purposes: a separately schedulable task defines the granularity at which OS can run, suspend, resume a thread at any time the OS offers isolation bound to a process (lives in an address space) App 1 address space identifies what Finite Progress Axiom: execution proceeds at some can be touched by the program unspecified, non-zero speed define the granularity at which Virtualizes the processor OS the OS offers scheduling and can programs run on machine with a seemingly infinite Hardware number of processors express concurrency a stream of instructions Allows to specify tasks that should be run concurrently... executed sequentially ...and lets us code each task sequentially 115 114
Overlapping I/O & How Threads Can Help Computation Request 1 Request 2 for (k = 0; k < n; k++) Thread 1 Thread 2 a[k] = b[k] × c[k] + d[k] × e[k] get network message (URL) from client get network message get URL from disk (URL) from client Consider a Web server get URL from disk (disk access latency) get network message from client (disk access latency) get URL data from disk send data over network send data over network compose response Time send response Total time is less than Request 1 + Request 2 117 116 Multithreaded Processing Why Threads? Paradigms To express a natural program structure updating the screen, fetching new data, receiving user Request Request Request input — different tasks within the same address space Queue Queue Dispatcher Workers To exploit multiple processors different threads may be mapped to distinct processors To maintain responsiveness Specialists splitting commands, spawn threads to do work in the Specialists Pipeline Dispatcher/Workers background Masking long latency of I/O devices do useful work while waiting 118 119
All You Need is Love A simple API (and a stack) All threads within a process share Syscall Description heap void Creates a new thread in thread, which will thread_create global/static data execute function func with arguments arg. (thread, func, arg) libraries Calling thread gives up processor. Scheduler can void Each thread has separate thread_yield() resume running this thread at any time program counter Wait for thread to finish, then return the value int registers thread passed to thread_exit. thread_join May be called only once for each thread. stack (thread) void Finish caller; store ret in caller’ s TCB and wake thread_exit up any thread that invoked thread_join(caller). (ret) 121 120 One Abstraction, Preemption Two Implementations Preemptive Kernel Threads yield automatically upon clock interrupts each thread has its own PCB in the kernel true of most modern threading systems PCBs of threads mapped to the same process point to the same physical memory Non-preemptive visible (and schedulable) by kernel explicitly yield to pass control to other threads User Threads true of CS4411 P1 project one PCB for the process each thread has its own Thread Control Block (TCB) [implemented in the host process’ heap] implemented entirely in user space; invisible to the kernel
Kernel-level Threads User-level Threads 0xFFFFFFFF 0xFFFFFFFF Kernel knows about threads Run OS-like code in user space Mail Mail existence, and schedules them real OS is unaware of threads as it does processes Emacs Emacs holds a single PCB for all user threads within the same Each thread has a separate process PCB each thread has associated a Stack 2 “the” Stack PCBs of threads mapped in the Thread Control Block (TCB) Stack 1 Apache Apache same process have kept by process in user space Heap Heap same address space User-level threads incur lower (includes stacks) Data Instructions Data page table base register overhead than kernel-level Instructions threads… different PC, SP, registers, interrupt stack …but kernel level threads Kernel Kernel simplify system call handling PCBs and scheduling PCBs 0x00000000 0x00000000 Kernel- vs. User-level Kernel- vs. User-level Threads Thread Switching Kernel-level Threads User-Level Threads Thread 1 Thread 2 Easy to implement: just like Ease of Requires implementing user-level process, but with shared U User implementation schedule and context switches address space Space Blocking system call blocks all K K Handling system Thread can run blocking threads: needs OS support for 3 1 calls systems call concurrently non-blocking system calls (scheduler activations) Kernel K 2 Space Cost of Thread requires three context Thread switch efficiently context switch switches implemented in user space
Threads considered harmful Creating a thread or process for each unit of work (e.g., user request) is Well conditioned dangerous Not well conditioned High overhead to create & delete thread/process Can exhaust CPU & memory resource Throughput Thread/process pool controls resource use Allows service to be well conditioned output rate scales to input rate excessive demand does not degrade pipeline throughput Load 128
Recommend
More recommend