By Alan Jern, Christo Rose, Alex Wang
Professor: Eddie Kohler
Office: Boelter 4531C
Office Hours: Monday 9-11 am
Textbook: Operating System Principles. Available at Course Reader Materials for $19.
1/3 Labs: There will be four labs for the quarter. The labs cover the following topics:
In addition, you will be required to complete one design project, which involves an extension of one of the four labs. You will need to create a design specification for some additional functionality, and begin its implementation. Individuals/teams will be assigned ahead of time to one of the four design projects.
1/3 Midterm and final: Both exams are open book and open notes.
1/3 Miscellaneous assignments, including:
Late Policy: Every student is allowed three free late days which they may use on any assignments throughout the quarter. After the free late days are gone, each day an assignment is submitted late will result in a grade reduction of about one letter grade.
What is a system? The course textbook, Operating System Principles, provides several examples of systems:
All of these things share some property that makes them systems. To capture this property, one might consider several definitions of "system". The American-Heritage Dictionary provides the following definition.
A group of interacting, interrelated, or interdependent elements that form a complex hole.
Alternatively, our class textbook provides the definition,
A set of interconnected components that has a specified behavior observed at the interface to the environment.
Finally, Professor Kohler's personal definition is
An object where an implementation property can affect functionality.
To better understand Professor Kohler's definition, consider the following example concerning the sorting problem and several well-known algorithms for solving it: Insertion Sort, Merge Sort, and Quicksort. First, we note the average and worst-case computational complexities of each algorithm.
| Insertion Sort | Merge Sort | Quicksort | |
|---|---|---|---|
| Average Complexity | O(n2) | O(n*log(n)) | O(n*log(n)) |
| Worst-Case Complexity | O(n2) | O(n*log(n)) | O(n2) |
On the basis of this information, Merge Sort appears optimal. However, in practice, Quicksort has better performance than Merge Sort. This is because (a) Quicksort can be done "in place", that is, it does not require additional allocation of memory, unlike Merge sort, and (b) the inner loop of the Quicksort algorithm is smaller, making it more amenable to compiler optimizations 1).
Additionally, for cases of small n (i.e. 8 < n < 20), Insertion Sort is the superior choice, namely because its inner loop is even smaller than that of Quicksort's, enabling even greater optimization.
This example illustrates how the theoretical properties or functions of a problem or model can be obscured, altered, or even reversed, when faced with real-world constraints during implementation.
Systems exhibit several hazardous properties. Designers of systems should always keep these in mind and try to minimize their influence.
Many systems often exhibit behavior that is unpredictable from its basic components and design. This property stresses the difference between a model or design of a system and the actual implementation of the system.
An example would be the famous (or infamous) Tacoma Narrows Bridge in Washington, a thin bridge built across a deep gorge. During one particular storm, the winds somehow created a resonant vibration with the bridge, causing it to undulate and twist wildly and ultimately collapse. This was an outcome that was completely unexpected, which the designers of course did not predict to happen, and only afterwards, did people know that a bridge could exhibit such behavior.
Another example would be Boston's Hancock Building, a long and narrow building. One problem of the Hancock Building was that its glass window panes would pop out due to pressure differences and the construction of the glass. Also, the building would sway during windy weather, and people in the upper floors would experience motion sickness, so more money was spent designing and installing a damper for the building. Later on, it was found that the building could even topple towards its narrow edges, not just its wide edges, so even more money was spent reinforcing those sides of the building. These were all unexpected results of the original design of the building.
This property says that a small change in one part of a system affects other parts far away, or as the general statement about propagation of effects states, "There are no small changes to a large system." It is important to always keep in mind how even the most minor differences might affect other parts of a system. Similarly, a minor fault in a system can eventually lead to major breakdowns. Thus when designing a system, it is advisable to limit the impact of any one part of a system on the other parts.
A great example or study of this property can be found in what Lorenz coined as "The Butterfly Effect." In his study of weather patterns, he began to realize that some minor changes in the values of his computer weather model would result in extremely different output.
This notion describes how not all parts of a system scale at the same rates. In other words, as the system is scaled higher (or lower), eventually something will break or become ineffective.
For example, one could ask why aren't people 20' tall? Or why aren't rats elephant-sized? One answer would be because of the scaling issues dealing with bone strength, which is determined by its cross section and thus scales at a rate of O(n2), and weight increase, which is determined by volume and thus scales at a rate of O(n3). In essence, there will be a point where if the scaling is constant for all parts of the system, the bones will crack under the weight of the body.
Also, in the example of networking, straight scaling of computers to a router in a star topology (one in which all networked computers are connected to a single central router through one communication link) would eventually clog up the network (O(n) scaling). In actual networks, scaling is handled by creating branched or hierarchical network structures (O(log n) scaling).
Another property seen in systems is that one must often sacrifice or reduce one aspect of a system in order to improve another aspect. Rarely can one greatly improve a part of a system without sacrificing something else. We saw several examples of this property in the M151B course when studying how to optimize a certain design for computer architecture.
A general example of this would be email spam filters, where a designer must balance the amount of false positives, where real mail gets blocked, and false negatives, where spam gets through. An decrease in one area would most likely cause an increase in the other. A designer could easily create a spam filter that offered no false positives at all, but of course this would mean that any and all mail would come through.
If systems had only drawbacks, we would never use them. However, systems do have some properties that make them essential.
Modern computer systems contain unprecedented complexity. Additionally, computer system technology continues to progress at an unprecedented rate, as described by Moore's Law.
One possible explanation for this phenomenon is that technological progress is propelled by a tight feedback loop: the next wave of technology is designed using the current computer technology; thus, the next wave after that can be developed even faster using the better technology. In fact, if we describe this relationship using the differential equation,
d(technology)/dt = technology
the solution is exponential.
Another important difference between computer technology (particularly software) and other forms of technology is that it is not constrained by physical limitations. In most engineering disciplines, all measurements contain some uncertainty or margin of error; in software every bit is either on or off, with no uncertainty.
The unprecedented complexity of computer systems requires that we use well-suited design techniques for handling complex systmems. A tremendously successful technique in common practice is the principle of modularity.
Modularity focuses on how a system is broken into subsystems, or modules. A good system will contain modules that have a well defined behavior and interact only at specified interfaces.
Modularity is one of the more important catagories dealing with complexity of systems. Not only does it serve to make a system simpler to maintain and understand, but modularity also helps prevent the propogation of negative effects. These advantages are quickly understood when considering functions and classes used by computer systems, but appear more subtlely in larger systems. For example, the cables on the Golden Gate bridge are each composed of 17,664 wires but may be treated as a single entity by designers concerned with the overall structure of the bridge.
In order for modularity to be helpful in handling complexity, it must be "good". Good modularity will have the following properties.
An operating system (OS) is a program that acts as an intermediary between user, computer, and hardware, providing applications with access to a abstract machine or virtual computer. This virtual computer virtualizes all of the computer's hardware, thereby enabling multiple applications and thus the user to access the hardware in a more performant, robust, neutral, and simple way than programming the hardware directly. The following figure illustrates the underlying modularity that an OS imposes on a computer system.
Applications
---------------------- <--- Abstract machine/virtual computer interface
OS kernel
The operating system enables a computer to function properly by providing protection and sharing, that is, preventing applications from breaking the computer and allowing multiple applications to be run at the same time.
An important aspect of the virtual computer interface is that it has system calls. These are a special type of function call provided by the kernel for applications to use.
The following example highlights only a few of the potential problems that a poorly-designed OS interface creates.
The goal of this interface is to enable programmers to read a line from a file, represented by a unique file descriptor (fd). The interface consists of the following two system calls.
int length_of_line(fd); // returns the length of the next line in file represented by fd int readc(fd); // returns next character in file represented by fd // returns -1 if EOF (end of file)
These two system calls can be used to read one complete line from a file.
int line_len = length_of_line(fd); char* line = malloc(line_len); int i; for (i = 0; i < line_len; i++) { line[i] = readc(fd); }
This interface "works" (i.e. it provides the necessary functionality), but it has some undesirable qualities in the areas discussed above in the section on modularity.
readc.length_of_line function. For example, imagine calling this function on a file with 2 GB of characters without a newline. Ideally, kernel operations should be relatively simple and bounded, which helps the OS to manage multiple simultaneous applications more easily.