Presentation is loading. Please wait.

Presentation is loading. Please wait.

Unix System Calls and Posix Threads

Similar presentations


Presentation on theme: "Unix System Calls and Posix Threads"— Presentation transcript:

1 Unix System Calls and Posix Threads

2 Overview Process-related Unix system calls Posix threads

3 Process-related Unix System Calls
A process in Unix consists of an address space and one thread Unix provides several process-related system calls: getpid(), getppid() Get unique id for process, for parent process Pid identifies both address space and thread fork(), execv() Create new processes exit(), wait() Terminate processes and synchronize with terminating process kill(), sigaction() Communicate with another process via signals parent process: we will see what is a parent process when we discuss fork()

4 Fork System Call fork() system call creates a new process
The original process is called the parent process The new process is called the child of the parent process Child process is an identical copy of the parent Thread state (registers) and address space are copied stack text data Address space SP PC Parent stack text data Address space SP PC Child

5 Fork After fork system call returns: What does this code print?
Both parent and child process start executing the instruction after fork To distinguish the two processes, fork returns PID of child in parent process, and 0 in child process Parent and child run code and modify data completely independently, how? What does this code print? Why the weird call? int n = 5; int pid = fork(); if (pid == 0) { // run child code n = n + 1; } else { // pid value > 0 // run parent code n = n - 1; } printf(“n = %d\n”, n); independent execution: because child is a separate process, with a separate copy of code, data, stack, etc., its own set of registers. code will print: n = 4 n = 6 or it will print: weird call: Allows sharing information implicitly between parent and child. The parent can setup any state that needs to be shared with the child before the call to fork. For example, say a variable could be set to a specific value. After fork, the child would see the value.

6 Crazy Fork What output does this code produce? int n = 5;
int pid = fork(); if (pid == 0) { n = n + 1; if (fork()) { } } else { n = n - 1; printf("n = %d\n", n);

7 Execv System Call execv() call allows running a new program
Fork creates a new process that is a copy of its parent, but it doesn’t allow running a new program When process calls execv, new program replaces current process stack text data Address space SP PC After execve stack text data Address space SP PC Before execve

8 Execv On execv system call:
New program is loaded from executable file on disk into current program’s address space Code and data regions are copied from disk Stack is initialized with activation frame of main() Processor registers are reinitialized New program’s process ID is the same as old program’s process ID execv() does not return, why? char *cmd = “/bin/ls”; char *arg1 = “-l”; char *args[3]; args[1] = arg1; args[2] = NULL; execv(cmd, args); // code doesn’t execute sketch shows a combination of fork and execv. fork creates a new process that is identical to the parent. execv replaces the child with a new program. this combination allows running the new program as a separate process while keeping the old process. args[0] should be initialized to “ls”, but it is not essential. does not return: because previous process has been discarded, unless exeve has an error

9 Exit System Call A process can terminate itself by calling the exit() system call On exit(retval) system call: Address space of the process is destroyed (memory for code, data, etc., regions is reclaimed) Process-specific OS state, e.g., open files, is destroyed retval is saved, can be returned to parent process Why is this useful? Thread state is destroyed When is this done? useful: parent can learn about exit status. for example, in the shell, $? shows the exit status of the child process that is last run by the shell. when is this done: recall that it is done when the next thread starts running

10 Wait System Call A parent process can wait for a child process to terminate by calling the wait() system call When child issues exit(retval), wait() returns retval What happens if child exits before parent issues wait? What happens if parent never issues wait()? child exits before parent: OS keeps the child’s exit retval (i.e., it keeps some minimal state for the child), until wait() is issued by the parent parent never issues wait: child is destroyed when parent exits

11 W: wait starts, C: wait continues, E: exit starts, D: exit done
Wait needs to handle 4 cases Parent issues wait before or after child’s exit Parent doesn’t issue wait, exits after or before child’s exit Parent Child E D W C Notice that in cases 1, 2 and 3, the parent exits after the child, and so we need to perform synchronization. This synchronization is needed so that wait can return the exit value of the child. Notice that in case 3, the parent doesn’t perform a wait, but the child doesn’t know that because it exits first, and so we still need to perform the synchronization. Notice that each arrow denotes a synchronization point. The target of the arrow (the arrow head) waits for the source of the arrow (and so target must happen after the source). For example, in case 1, “C” in the parent must happen after “E” in the child. Each of these synchronizations can be implemented using semaphores. The target of the arrow should perform a down(), while the source should perform an up(). Since there are two different types of arrows, two different semaphores are needed (one for E->C/E, one fore C/E->D). In case 4, the parent exits before the child, and so no synchronization is needed. Note that the child thread is destroyed after the D (exit done) point. W: wait starts, C: wait continues, E: exit starts, D: exit done

12 Kill and Sigaction System Calls
Unix allows processes to send signals (or messages) to itself or to other processes by calling the kill() system call Receiver process handles signals similar to interrupts When the Receiver process runs the next time, instead of performing its normal execution, it starts executing a function called a signal handler When signal handler finishes, normal execution continues The sigaction() system call allows a process to setup the signal handler function When no handler is setup, receiver process is forced to exit Receiver process exits when it is scheduled to run next, why? We use signals in lab 3 to simulate timer interrupts. Receiver process exits when it runs next: a process exits by calling thread_exit on itself, so thread_exit assumes that the calling thread is exiting. So a thread cannot directly call thread_exit to force another thread to exit. One reason that thread_exit is not invoked on other threads directly is that a thread R (receiver) might be holding a lock, and on exit, it will release the lock. however, unlock may assume that the thread that acquired the lock (thread R) will release it. If thread S (sender) called thread_exit on thread R, then the unlock would be performed by thread S, so it will appear that thread R acquired the lock, while thread S is releasing it. Similarly, on a multi-processor, thread R might be running when thread S calls exit on it from another processor. Unless proper synchronization is done, this could cause race problems. The moral is that it is best to die by oneself 

13 Code Examples Read the man pages of the Unix system calls if you have trouble understanding their semantics On google: man fork Some code examples are available on the web site shell.c A simple shell program in Unix unix-signal.c A program that shows how signals are used in Unix

14 Posix Threads Recall that a Unix process consists of an address space with one thread Within main(), this thread is running POSIX Threads or the pthreads system calls allow creating additional threads in a Unix process

15 Posix Threads API pthread_create(thread, attr, start_routine, arg)
Returns new thread ID in thread Executes function specified by start_routine(arg) pthread_exit(status) Terminates current thread, returns status to a joining thread pthread_join(thread_id, status) Blocks thread until thread specified by thread_id terminates Return value from pthread_exit is passed in status pthread_yield() Thread gives up processor and enters the run queue

16 Posix Threads Synchronization API
Pthreads provides mutex, semaphores, and condition variables Mutex Semaphores pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mut); pthread_mutex_unlock(&mut); sem_t sem_name; sem_init(&sem_name, 0, 0); /* 2nd arg is flag, 3rd arg is init value */ sem_wait(&sem_name); /* wait operation */ sem_post(&sem); /* signal operations */

17 Posix Monitor Example Say a thread wishes to wait until x > y
Another thread signals when x > y int x,y; pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_lock(&mut); while (x <= y) { pthread_cond_wait(&cond, &mut); } /* operate on x and y */ pthread_mutex_unlock(&mut); pthread_mutex_lock(&mut); /* modify x and y */ if (x > y) pthread_cond_signal(&cond); pthread_mutex_unlock(&mut);

18 Posix Code Examples Some posix code examples are available on the web site pthread-example.c Several threads are created and run without synchronization pthread-example-sync.c Several threads are created and run with synchronization

19 Summary Unix OS provides various system calls for managing processes
fork creates a new clone process execv loads a new program in an existing process exit ends a process wait allows a parent process to wait for a child’s exit kill and sigaction are used to send signals to processes, similar to how device controllers interrupt the CPU Pthreads is a standardized API for creating and managing threads in Unix OSes

20 Think Time What happens when the various system calls we have discussed fail (due to some error)? Think about how the OS handles the various wait scenarios, i.e., how is the synchronization between the parent and the child implemented in the four cases? What are the steps involved in sending and receiving signals? 1. When Unix system calls fail, their return value is -1, and they set a special variable called errno that indicates the cause of the error. You should always check the return value of a system call to ensure that it has not failed. 2. Sync between parent and child: implemented using two semaphores or condition variables 3. Steps involved in sending and receiving signals: sender uses kill system call to send signal to another process, receiver registers a signal handler using sigaction call. When signal is received, the signal handler code is invoked in the receiver.


Download ppt "Unix System Calls and Posix Threads"

Similar presentations


Ads by Google