COMP 3000 Lab 3 2010 Soln: Difference between revisions
Line 3: | Line 3: | ||
===Processes and Threads=== | ===Processes and Threads=== | ||
# The program [http://homeostasis.scs.carleton.ca/~soma/os-2010f/lab3/threads.c threads.c] is a multithreaded producer/consumer program. Unfortunately it consumes faster than it produces, resulting in an error. Why does it not print the same number every time?<br /><br />A: This has to do with the fact that we have two processes running on a system without any sort of locking mechanism. This results in a race condition. If both processes ran for exactly the same amount every time you ran them, then the race condition would always appear at the same value. Unfortunately, this is not the case. There are a number of factors in a modern system which can affect the running time of a process. They include: | # The program [http://homeostasis.scs.carleton.ca/~soma/os-2010f/lab3/threads.c threads.c] is a multithreaded producer/consumer program. Unfortunately it consumes faster than it produces, resulting in an error. Why does it not print the same number every time?<br /><br />A: This has to do with the fact that we have two processes running on a system without any sort of locking mechanism. This results in a race condition. If both processes ran for exactly the same amount every time you ran them, then the race condition would always appear at the same value. Unfortunately, this is not the case. There are a number of factors in a modern system which can affect the running time of a process. They include:<br />(a) Other processes on the system<br />(b) Hardware (which interrupts the CPU to get serviced)<br />(c) The CPU, memory, cache<br />Because of this, the scheduling of the two processes may look more like the diagram below, where the read lines indicate the servicing of an interrupt request. In order to always stop at the same number every time, each interrupt service would have to take exactly the same amount of time, and the processes would never be allowed to have their running time shortened or lengthened by even a few clock cycles. Being strict on execution time down to the clock cycle is not feasible on modern systems.<br /><br /> | ||
(a) Other processes on the system | # The program [http://homeostasis.scs.carleton.ca/~soma/os-2010f/lab3/passstr.c passstr.c] is a multithreaded program using the <tt>clone</tt> function call. What is wrong with the way this program blocks, waiting for the string to arrive in the buffer?<br /><br />A: The program is blocking by busy waiting on the first character in the string. Busy waiting is bad because it ties up system resources needlessly. Furthermore, it is looking at the first character in the string, which means if a process switch happened after the first character was written but before the rest of the string was written, then only the first part of the string would be displayed on the string (since the consumer would read the string before it was all completely there). | ||
(b) Hardware (which interrupts the CPU to get serviced) | |||
(c) The CPU, memory, cache | |||
Because of this, the scheduling of the two processes may look more like the diagram below, where the read lines indicate the servicing of an interrupt request. In order to always stop at the same number every time, each interrupt service would have to take exactly the same amount of time, and the processes would never be allowed to have their running time shortened or lengthened by even a few clock cycles. Being strict on execution time down to the clock cycle is not feasible on modern systems. | |||
# The program [http://homeostasis.scs.carleton.ca/~soma/os-2010f/lab3/passstr.c passstr.c] is a multithreaded program using the <tt>clone</tt> function call. What is wrong with the way this program blocks, waiting for the string to arrive in the buffer?<br /><br />A: The program is blocking by busy waiting on the first character in the string. Busy waiting is bad because it ties up system resources needlessly. Furthermore, it is looking at the first character in the string, which means if a process switch | |||
happened after the first character was written but before the rest of the string was written, then only the first part of the string would be displayed on the string (since the consumer would read the string before it was all completely there). | |||
===Fork & Exec=== | ===Fork & Exec=== |
Revision as of 12:17, 25 November 2010
Part A (Mandatory)
Processes and Threads
- The program threads.c is a multithreaded producer/consumer program. Unfortunately it consumes faster than it produces, resulting in an error. Why does it not print the same number every time?
A: This has to do with the fact that we have two processes running on a system without any sort of locking mechanism. This results in a race condition. If both processes ran for exactly the same amount every time you ran them, then the race condition would always appear at the same value. Unfortunately, this is not the case. There are a number of factors in a modern system which can affect the running time of a process. They include:
(a) Other processes on the system
(b) Hardware (which interrupts the CPU to get serviced)
(c) The CPU, memory, cache
Because of this, the scheduling of the two processes may look more like the diagram below, where the read lines indicate the servicing of an interrupt request. In order to always stop at the same number every time, each interrupt service would have to take exactly the same amount of time, and the processes would never be allowed to have their running time shortened or lengthened by even a few clock cycles. Being strict on execution time down to the clock cycle is not feasible on modern systems. - The program passstr.c is a multithreaded program using the clone function call. What is wrong with the way this program blocks, waiting for the string to arrive in the buffer?
A: The program is blocking by busy waiting on the first character in the string. Busy waiting is bad because it ties up system resources needlessly. Furthermore, it is looking at the first character in the string, which means if a process switch happened after the first character was written but before the rest of the string was written, then only the first part of the string would be displayed on the string (since the consumer would read the string before it was all completely there).
Fork & Exec
- What is the difference between the clone and the fork function call?
IPC
Examine the program given in wait-signal.c. It multiplies two matrices together using the standard trivial algorithm (which also happens to be a n3 algorithm). It spawns off a child process to compute the value of each element in the resulting matrix. The program has a problem, however, in that it fails to pass the resulting values back to the parent process in order to give the right result. In this section, we will examine various methods for passing data between processes.
- Signals
Signals can be sent to each process running on the system. Signals, however, don’t allow the passing of any data along with the signal. Therefore, they are most useful for triggering actions.
- The kill command actually sends signals to processes. What signal does the kill command by default send to a process?
- Modify the wait-signal.c file to use the signal function to install the signal handler instead of the sigaction function call. You can have it install the child handler alt signal handler instead of the child handler signal handler. What line did you add to install the signal handler to child handler alt?
- Modify the wait-signal-1.c file to ignore the abort signal. What line did you have to add to do this?
Note: The file names may have been switched. Try using the wait-signal1.c for part 2 and wait-signal.c for part 3 - --AbsMechanik 15:11, 5 October 2010 (UTC)
- Pipes
Pipes (also called FIFO’s) allow two processes to communicate through a file handle. One process writes data into a file handle and the other process can then read that data out through a related but different file handle.- What happens to file descriptors across an exec call? Write a small program that tests this behavior, i.e. that opens a file, calls execve, and then the new program attempts to read from the previously opened file descriptor. Explain how this program behaves.
- Compile and run pipe.c. Notice how data is sent through the pipe by writing to one end of the pipe in the child and reading from the other end of the pipe in the parent. Also notice how the message Finished writing the data! is never displayed on the screen. The problem has to do with the SIGPIPE signal. What is the problem?
- Shared Memory
- Shared memory regions are controlled by the kernel to prevent other processes from accessing the memory without permission. Like files in Unix, the shared memory regions are given read, write and execute permission. These permissions are specified in the call to shmget. Where in the arguments to shmget are the permissions specified?
- The permissions must be specified as a value. By reading the manpage of chmod, determine what the permission 0760 means.
- What number is going to be required in order for two processes owned by the same user to be able to read and write to the shared memory?
Part B (Optional)
The following exercises are optional.
Processes
- From class, you know that the process descriptor contains numerous information about a running process on the system. The task structure in Linux is called struct task struct. By examining the source of the Linux kernel, determine what source file this structure is defined in. The grep command may be useful in locating the correct file.
- Figure 6.3 (page 213) in your textbook contains a list of common elements found in a process table. Determine at least one variable in the Linux task structure which is related to each element listed in Figure 6.3. You may omit address space and stack.
Fork & Exec
- Examining the flags that can be passed to the clone function call. Choose 5 flags and describe a situation in which each of them would be useful.
Find the portion of the Linux kernel that implements the fork, clone, and vfork system calls for i386 systems. Based upon this code, could Linux instead just have one of these system calls?
If so, which one, and how would you implement userspace “wrappers” that would provide identical functionality for the other two calls?
If not, why are all three necessary? Explain.(For this question, ignore issues of binary compatibility.) - File descriptors 0, 1, and 2 are special in Linux, in that they refer to standard in, standard out, and standard error. Does the Linux kernel know they are special? Explain, referring to appropriate parts of the Linux kernel source.
IPC
In this section, you will be modifying the program wait-signal to correctly compute the value of the matrix multiplication.
- Signals
Describe in words how you might modify the wait-signal program to correctly pass back the value computed in the child to the parent using only signals. Remember that signals do not allow data to be passed back and forth. Also keep in mind that there are only around 32 signals that can be sent to a process. You do not have to implement your answer, only describe what you would do. - Pipes
Modify the wait-signal.c program to pass the appropriate matrix data back to the parent via a pipe. Remember that you will also have to pass back the x and y locations that the data should be put in. What is your updated main function? - Shared Memory
Modify wait-signal.c to send data back to the main process using shared memory. You will need to use the functions shmget and shmat.