**Main Learning Goal:** How do we design the operating system to optimally manage access to hardware resources across a variety of applications? Which applications (or sub components) of applications need direct access to hardware resources for customization through privileged instructions? And how we can ensure those components (and only those components) have direct access to the hardware when they need it?
# Key Terms
- **OS Structure**: the way the operating system is organized with respect to the applications that it serves and the underlying hardware that it manages
- Key goals for the OS:
- **Protection**: the OS protecting the system from the user, the user from the system, the user from other users, and the user from his own mistakes
- **Performance:** time taken for the OS to perform services on behalf of the application
- **Flexibility:** services provided by the OS are not one size fits all. Can be customized per application
- **Scalability:** the OS performance increases as hardware resources increase
- **Agility:** ability of the OS to adapt to changes in application needs and/or resource availability
- **Responsiveness:** how quickly the OS reacts to external events (e.g. clicking the mouse)
- **Monolithic OS:** an OS structure that includes the entire OS (hence monolithic) running in its own hardware address space, with new applications started in their own respective address spaces. This ensures separation between applications and the OS. When the application needs to directly access underlying hardware (e.g. transferring something from RAM to the hard drive), control is transferred to the OS by executing instructions that are in its hardware address space
![[Screenshot from 2024-09-22 15-54-53.png]]
- **DOS-like OS structure:** similar to monolithic structure, except there is no well-defined separation between apps and OS (i.e. apps execute in the same address space as the OS). Apps can run faster because they don't need to transfer control to the OS to access system services. But this means less protection - user apps can easily disrupt the system without the OS's input
![[Screenshot from 2024-09-22 16-01-20.png]]
- **Microkernel-based OS Structure:** A small microkernel runs in privileged mode and manages access to hardware while providing access to simple abstractions, such as threads, address spaces, and inter-process communication. Importantly, the microkernel does *not* implement any policies (that is, *how* these abstractions function). Instead, it just provides access to mechanisms. OS services then run on top of the microkernel in their own address spaces and implement policies for the microkernel functions, as well as combine those functions to provide new services. The OS services execute with the same privilege as the applications themselves. Apps, similarly to OS services, have their own address spaces.
![[Screenshot from 2024-09-22 16-22-02.png]]
- **SPIN OS Structure:** uses a think microkernel (labeled "SPIN" below), just like in the microkernel-based approach. However, extensions to the microkernel exist in the same hardware address space as the microkernel itself. Logical boundaries are erected between microkernel extensions by leveraging the capabilities of Modula 3, a strongly-typed programming language. The logical separation provides protection, the extensions provide flexibility, and the fact that the extensions exist in the same address space as the microkernel provide performance.
![[Screenshot from 2024-09-22 17-06-53.png]]
- **Exokernel OS Structure:** the architecture has a very thin exokernel, whose job is to receive requests for resources, provide resources to satisfy the request, and generate & validate encrypted keys to ensure that only the requester can access the requested resource. The requests come from library OSes, which are essentially entire OSes in their own rights. They define all of the semantics of all of the internal services that they use. Library OSes can download performance-critical code into the exokernel itself, allowing it to execute with border crossing between address spaces.
![[Screenshot from 2024-09-22 17-52-38.png]]
- **L3 Microkernel OS Structure:** essentially a microkernel architecture, but makes its microkernel processor-specific. The core thesis of L3 is that if you have a set of minimal abstractions stored in the microkernel which cover *most* of the cases associated with process system calls (address space, threads, interprocess communication, UIDs) and build these microkernel abstractions to take advantage of a *specific* processor architecture, you can build efficient *processor-independent* abstractions at the higher levels. That is, we make the primitives extremely hardware-specific at the low level so that hardware-agnostic processes that use these primitives in the application layer can be very fast.
![[Screenshot from 2024-09-22 20-32-10.png]]
# Notes
- What is the difference between flexibility & agility?
- Flexibility focuses on customizing functionality between applications. Agility focuses on the requirements changing in a single applications, and also includes changes that happen on the hardware level as well
- Why did DOS use this structure if it compromises protection so much?
- In the early days of computing, it was assumed that only 1 user would be using a PC at a time, with 1 application executing. The opportunities for disrupting the OS are much lower when the usage of the system is low. With many users and many simultaneous applications running, the potential for corrupting the OS increases substantially. Thus, the higher performance of the DOS structure was prioritized
- What is a downside of monolithic structure?
- All of the OS services are rolled together, so we cannot customize specific OS module for different applications.
- What are examples of applications that would require OS module customization?
- For example, video games require very high responsiveness to mouse and keyboard input. On the other hand, a prime factorization application needs to prioritize sustained CPU time to crunch through all of the numbers. Customizing task scheduling (e.g. how long time slices are, whether or not the OS interrupts the CPU immediately in response to input, etc) can help each application achieve its goals
- What opportunities exist for OS customization?
- Each service provided by the OS has a goal or set of goals (e.g. memory management aims to isolate each process's memory from each other, abstract away the underlying hardware details of memory access, and efficiently move data between RAM and the hard drive). Many OS services run particular algorithms or use particular data structures that determine how the service implements its goal. If we can define those algorithms or data structures, we can alter the characteristics to suite a particular application. For example, in memory management, we can alter the page replacement algorithm or change how often it runs in order to achieve the desired memory throughput and latency for the current application.
- What are the advantages of the microkernel-based OS structure?
- It provides very high flexibility and agility. We can define multiple implementations for each OS services, allowing applications to use the implementation that best fits their needs. In addition, we have enhanced protection because now each OS service *and* each application is isolated in its own hardware address space.
- What is the main disadvantage of the microkernel-based OS structure?
- Performance. If multiple OS services need to be called, we need to make multiple IPC calls to the microkernel, which then makes IPC calls to the OS service that we need. Each OS service call that the application makes may need multiple OS service calls to complete, so the number of IPC calls needed can grow very quickly.
- Why do changes in address space incur a performance cost?
- For two reasons:
- Context switching from one address space to another invalidates cache contents. So we need to do a lot of loading from physical memory to repopulate the cache for the new process
- Frequently need to copy data from the user process address space to the system address space
- Consider the OS attributes of performance, protection, and extensibility. Which attributes do the DOS, microkernel, and monolithic OS designs have?
- Microkernel
- Extensibility
- Protection
- DOS
- Extensibility
- Performance
- Monolithic
- Protection
- Performance
- How is DOS extensible?
- Since there is no separation between applications and OS hardware address spaces, applications build new versions of system services to cater to specific applications
- What are the two premises that the SPIN and exokernel OS structures are based on?
- Microkernel-based designs compromise on performance due to frequent border crossings between the microkernel address space & the app/OS service address space
- Monolithic-based designs compromise on extensibility by contain all OS code in a single "blob" that needs to be regenerated/rebuilt if any module is changed
- Given our previous discussions, what are the main goals for an OS structure?
- Thin like a microkernel - it contains only mechanisms, not policies
- Performant like DOS - can access resources without border crossings
- Flexible like a microkernel - can redefine OS services easily for specific application
- No trade off between protection and performance like a monolith - can offer all of the above services without compromising on either protection or performance
- What is SPIN's approach to extensibility?
- **Key idea:** make extensions as cheap as procedure calls by relying on the attributes of a strongly-typed programming language to allow us to provide logical protection between the microkernel and its services even though they exist in the same hardware address space.
- Co-location of kernel and extensions to the kernel in the same address space, which eliminates border crossings when calling customized OS services.
- The compiler enforces modularity to give guarantees about protection even though the kernel and extensions exist in the same address space. It achieves this using a strongly typed programming language.
- Data abstractions provided by the programming language, such as an object, provide logical protection between the microkernel and its extensions. This way, we don't need to separate them at the hardware address space level.
- What strongly typed programming language was used to program the SPIN operating system?
- Modula 3
- How do Modula 3 pointers differ from C pointers? How does this help with logical protection?
- Pointers in Modula 3 are type-specific, which improves memory safety, error prevention, and security.
- What are the interface procedures that SPIN provides by default? (all of these are provided as header files to be implemented by microkernel extension implementations)
- Memory management
- Physical address
- Allocate, deallocate, reclaim
- Virtual address
- Allocate deallocate
- Translation
- Create/destroy address space, add/remove mapping between virtual pages and physical frames
- Event handlers
- Page fault, access fault, bad address
- CPU Scheduling
- SPIN abstraction: strand - unit of scheduling in SPIN
- Semantics defined by extension. Each process can then have its own unit of scheduling
- Event handlers
- Block, unblock, checkpoint, resume
- SPIN global scheduler
- Interacts with application thread package
- What are the mechanisms in place for implementing secure binding in the Exokernel OS architecture?
- Hardware mechanisms, e.g. TLB entry
- Software caching, e.g. "shadow" TLB in software for each library OS
- Downloading code into the kernel - functionally equivalent to SPIN extensions (i.e. extensions to the kernel that live in the kernel's address space but are logically separated)
- How do SPIN and Exokernel (extended kernel approaches) compare to monolithic structures and microkernel structure? Metric considered are space (size of codebase needed to implement the OS) and time (how long does an application take to execute).
- SPIN and Exokernel were much faster than microkernel
- SPIN and Exokernel were about as fast as a monolithic kernel