COSC243 Part 2: Operating Systems Lecture 16: Threads and data sharing Zhiyi Huang Dept. of Computer Science, University of Otago Zhiyi Huang (Otago) COSC243 Lecture 16 1 / 24
Overview Last lecture: Hierarchical structure in operating systems System calls and interrupts Representing processes in operating systems Overview of Process Scheduling This lecture: Cooperating processes Communication between parent and child processes Shared memory and pipes Threads Inter-process communication Zhiyi Huang (Otago) COSC243 Lecture 16 2 / 24
Cooperating Processes Some terminology: Cooperating processes: where the execution of one process can affect the execution of another. Independent processes: where the execution of one process cannot affect the execution of another. Naturally, any processes which share data are cooperating processes. Zhiyi Huang (Otago) COSC243 Lecture 16 3 / 24
Why Allow Processes to Cooperate? What are some advantages of process cooperation? Information sharing. Two processes might want to access the same data. E.g. many web server processes accessing the same database. Computation speedup. To introduce some parallelism into program execution. For example, OpenMP and Message Passing Interface (MPI) are parallel programming environments that allow processes to be executed in parallel while enabling sharing of information. Modularity. Dividing system functions into multiple processes. Zhiyi Huang (Otago) COSC243 Lecture 16 4 / 24
Communication between Parent and Child Processes Recall the process tree we saw in the last lecture: init daemon login bash1 bash2 bash3 system proc application sys proc sys proc A process can create a child process to do a particular task. But to do so, it has to be able to communicate with its child. Zhiyi Huang (Otago) COSC243 Lecture 16 5 / 24
Creating Child Processes in UNIX In UNIX, a child process is created with a system call called fork. fork creates a new process, consisting of a copy of the address space of the parent process. System calls are functions, and functions can return values: fork is no exception. Both parent and child processes continue after the fork function call but a different value for the function is returned in the two cases: the value for the child process is 0. the value for the parent process is the PID of the child. (By consulting this value, each process knows whether it s the parent or the child.) The child process then may or may not execute an execlp command, which loads a new program into its memory space (erasing the copy of the parent). Zhiyi Huang (Otago) COSC243 Lecture 16 6 / 24
Communication Between Parents & Children Some questions: Why is the parent s address space copied to the child process if execlp is just going to wipe it all out? ANS.: BECAUSE A., THE CHILD PROCESS MAY NOT CALL execlp, B., execlp STILL NEEDS THE SPACE TO PASS PARAMETERS, AND C., COPY-ON-WRITE (COW) IS USED TO AVOID THE COPYING. Why is the parent process given the child process PID? A: SO IT CAN KEEP TRACK OF THE CHILD PROCESS WHICH IS GOING TO CARRY OUT THE COMPUTATION. After a process has created a child process, it can execute a wait system call. wait moves a process off the ready queue, until the child process has terminated. When the child process has terminated, it can return its status to the parent. Zhiyi Huang (Otago) COSC243 Lecture 16 7 / 24
Process termination When a process has executed its last statement, it executes a special function: the exit system call, at which point, it may return its status to its parent process (the one waiting for it to terminate); all its resources (main memory, open files etc) are deallocated by the operating system. Processes can also die more violently: they can be terminated by other processes (e.g. in UNIX send signals with kill). Important constraint on which processes a process can kill: YOU CAN ONLY KILL YOUR OWN PROCESSES (CREATED BY THE SAME USER). Orphan process: a process whose parent terminated (inherited by init). Zombie process: one which terminated, but its live parent process is not WAITING for it. Since no process is receiving its exit status, it stays in the process table. Zhiyi Huang (Otago) COSC243 Lecture 16 8 / 24
Shared Memory: A Simple Kind of Data Sharing The memory mapping mmap family of system calls: allow two processes to share some region of their memory space. P1 map memory P2 Operating System This is achieved by creating a memory region that can be shared by other processes. Zhiyi Huang (Otago) COSC243 Lecture 16 9 / 24
An Example of Cooperation: The Producer-Consumer Problem A producer process writes data to a buffer of fixed size. A consumer process reads data from the buffer. The two processes are being scheduled independently by the CPU. Obviously, the producer process must wait if the buffer gets full; the consumer process must wait if the buffer is empty. This is a taster for the issue of process synchronisation. Zhiyi Huang (Otago) COSC243 Lecture 16 10 / 24
Pipes (in UNIX) cat test.txt grep party What s happening here? We re typing the command to the shell. When you hit return, the shell process normally forks a child process, which is told to execute the specified program. When you link two programs with a pipe, the shell process first sets up a buffer in memory, then forks two child processes, which are to read / write to this buffer. Zhiyi Huang (Otago) COSC243 Lecture 16 11 / 24
Threads Pipes provide a simple method for sharing data. Operating systems frequently support a special kind of processes called a thread to allow more complex data-sharing. A standard process has a data section, code section, a program counter, a register set, a stack space, info about open files, allocated I/O devices etc. A thread just has a program counter, a register set and a stack space. You can have several threads within a single process, using the same code section, data section, memory and I/O resources. Zhiyi Huang (Otago) COSC243 Lecture 16 12 / 24
Threads process thread1 program counter registers stack space code section data section O/S management info (open files, allocated devices etc) task thread2 program counter registers stack space thread3 program counter registers stack space The code section, data section, and O/S housekeeping info of a process is collectively known as a task. A task with just one thread is called a heavyweight process. A thread is also known as a lightweight process. Zhiyi Huang (Otago) COSC243 Lecture 16 13 / 24
Operations on Threads Threads and processes can do a similar range of things. A thread can wait while an I/O process completes (called blocking). A thread can be in different states: ready, blocked, running or terminated. A thread can create child threads. Zhiyi Huang (Otago) COSC243 Lecture 16 14 / 24
Two Kinds of Thread User-level threads: implemented in user-level libraries, without the need for system calls. These are the fastest kind of thread to switch between. But then the kernel doesn t know about individual threads within a process. Why should that matter? (I) UNFAIRNESS: ONE PROCESS MIGHT HAVE 100 THREADS, ANOTHER PROCESS JUST ONE. THE KERNEL GIVES THEM EQUAL TIME IN THE CPU. (II) SYSTEM CALLS. IF A THREAD MAKES A SYSTEM CALL, THEN THE WHOLE (HEAVYWEIGHT) PROCESS IS SUSPENDED UNTIL IT S COMPLETED; THAT INCLUDES ALL THE OTHER THREADS. Kernel-level threads: implemented via system calls. In this case, the kernel knows about individual threads. But switching between threads is slower. Zhiyi Huang (Otago) COSC243 Lecture 16 15 / 24
Advantages of Threads What s useful about threads? Responsiveness. Multithreading an interactive application may allow a program to continue running, even if part of it is waiting. Resource sharing. We don t need special setups for shared memory when implementing communicating processes as threads in the same task. Economy. Thread creation is easier. Switching between threads is faster than between (heavyweight) processes, because there s less to change. Scalability. Easy to work on multiprocessor architectures. Problems with threads? USER-LEVEL THREADS CAN T HAVE THE FAIR SHARE OF THE CPU TIME; KERNEL THREADS IS SIMILAR TO PROCESSES; SHARING BY DEFAULT CAUSES DATA RACE PROBLEMS. Zhiyi Huang (Otago) COSC243 Lecture 16 16 / 24
Servers as Threads A web server is a process that provides data over the web to requesting clients. (Possibly a large number of them.) Imagine a queue of client requests arriving in an input buffer. If we implemented the web server as a single process, what would the problem be? THE WEB SERVER WOULD BE INEQUITABLE: THE CLIENTS AT THE END OF THE QUEUE WOULDN T GET ANY SERVICE UNTIL THE ONES ON THE FRONT HAD BEEN FULLY SERVICED. The web server has to create a thread to deal with each separate request that arrives. In this approach: One thread is the daemon: it does nothing but listen for new requests. Each time a new request is detected, a new thread is created to service this request. Zhiyi Huang (Otago) COSC243 Lecture 16 17 / 24
Gobbledegook? Because kernel thread management is done by the operating system, kernel threads are generally slower to create and manage than user threads. However, since the kernel is managing the threads, if a thread performs a blocking system call, the kernel can schedule another thread in the application for execution. (Silberschatz et al.) Zhiyi Huang (Otago) COSC243 Lecture 16 18 / 24
Java threads Since Java runs on a virtual machine, it can provide support at the language level for creation and management of threads. Simplest way to make a new thread is to extend the class Thread: public class Worker1 extends Thread { } public void run() { System.out.println("I am a worker thread"); } public class First { public static void main(string args[]) { Thread runner = new Worker1(); runner.start(); System.out.println("I am the main thread"); } } Zhiyi Huang (Otago) COSC243 Lecture 16 19 / 24
Java threads Another way to create a new thread is to define a class that implements the Runnable interface. public interface Runnable { public abstract void run(); } public class Worker2 implements Runnable { public void run() { System.out.println("I am a worker thread"); } } public class Second { public static void main(string args[]) { Thread thrd = new Thread(new Worker2()); thrd.start(); System.out.println("I am the main thread"); } Zhiyi Huang (Otago) COSC243 Lecture 16 20 / 24
More on Java threads As well as threads defined in a Java program, there are a number of extra threads running on behalf of the JVM. For instance: a thread to listen and react to the mouse/keyboard; a thread to do garbage collection; a thread to handle timer events (e.g. the sleep() method). The JVM will implement threads in different ways in different versions, and in different operating systems. For instance, on the Linux lab machines: Java version 1.18 employs user-level threads. Java version 1.4 employs kernel-level threads. Zhiyi Huang (Otago) COSC243 Lecture 16 21 / 24
Signals Signals are important communication channels between the OS kernel and processes and between processes. A process can install a handler (function) for a signal using the system call signaction(). The default action for a signal is usually to kill/terminate the process if a handler is not installed. Other actions are ignore, core (dump a large file for debugging), stop(stop the process), and continue. The last two actions are used by debuggers like gdb to debug a program. Use man 7 signal on a Linux system to find more details of signals. Zhiyi Huang (Otago) COSC243 Lecture 16 22 / 24
Signal Types (partial list) SIGHUP (1, Term), Hangup detected on controlling terminal or death of controlling process SIGILL (4, Core), Illegal Instruction SIGABRT (6, Core), Abort signal from abort(3) SIGFPE (8, Core), Floating point exception SIGKILL (9, Term), Kill signal SIGSEGV (11, Core), Invalid memory reference SIGPIPE (13, Term), Broken pipe: write to pipe with no readers SIGALRM (14, Term), Timer signal from alarm(2) SIGTERM (15, Term), Termination signal SIGUSR1 (30,10,16, Term), User-defined signal 1 SIGUSR2 (31,12,17, Term), User-defined signal 2 SIGCHLD (20,17,18, Ign), Child stopped or terminated SIGCONT (19,18,25, Cont), Continue if stopped SIGSTOP (17,19,23, Stop), Stop process Zhiyi Huang (Otago) COSC243 Lecture 16 23 / 24
Summary and Reading Creating a child process Shared memory Pipes Threads Signals For this lecture, you should read Chapter 4 (Sections 1 4) of Silberschatz et al. For next lecture, you should read Chapter 5 (Sections 1, 2, 3 and 7). Zhiyi Huang (Otago) COSC243 Lecture 16 24 / 24