An operating system is considered to be one of the most complex software designs that we see today in the field of computer science. Starting from your mobile device to laptop to any other computer, operating systems is the key technology that enables us to use those devices as needed. Without an operating system, the hardware devices would simply be a complex circuit design that no one would ever understand to utilize it the way we do today. Inside operating systems, kernels play a major role in bridging the gap between hardware and software by providing a communication platform for user level applications. My previous blog titled, "The heart of computing devices" contains a broader description about kernels and how they work.
Designing an operating system is not at all an easy task. Understanding the different paradigms, architectures, hardware, design decisions etc, are just tough decisions that end up in major tradeoffs in some other aspects. Many operating system designs that we see today are never perfect due to this reason. This blog addresses the major aspects that we need to look into when designing our very own operating system and how the operating systems have evolved over time. The legendary Andrew Tanenbaum's, "Modern Operating Systems" book has been taken as guidance for this blog and following are the topics being addressed.
What is an Operating System
Why is it hard to design an Operating System
How to Design your own Operating system
Summary
What is an Operating System
An operating system is a software that provides services for application programs and users, by connecting the user space applications with the underlying hardware. All computing devices that we see today, including small devices and firmware, require an operating system to function. Some of the major tasks of operating systems are, Memory Management, Disk Management, Process Scheduling, File Management, Security, Administration, Resource Allocation etc.
Some of the leading operating systems that we see today are Microsoft's Windows, which holds a huge market share globally, followed by Apple's MacOS and Linux operating systems. The market also fights with the underlying operating system architecture on Exokernels, Micro kernels, Monolithic Kernels and hybrid kernel approaches.
MacOS : Is a series of graphical user interface based operating system developed by Apple. Inc.
Microsoft Windows: Is a series of graphical user interface operating system, developed, marketed and sold my Microsoft.
Linux: A Unix like operating system series, assembled under the model of free and open source software.
Android: A Linux based operating system, specifically developed for touch screen mobile devices such as smart phones and tablets.
iOS: This is a mobile operating system developed and distributed by Apple. Inc. This can run on Apply iPhones and Apple's other devices like tablets.
BSD/OS: has a reputation for reliability in server roles. The renowned Linux programmer and Author, W. Richard Stevens, was using this for his own personal web-servers.
Why is it Hard to Design an Operating System?
With the advancement of technology, developers and designers come up with many different hardware levels, to cope up to the requirements of the user. According to Moore's Law, computer hardware improves by a factor of 100 every decade. So the latest operating systems developed are said to be better and more complex than before. But, is that really the case? Some operating systems have gotten worse with time in terms of reliability. With time, the requirements people want changes rapidly. With this the development and design of operating systems get worse day by day. Some of the identified issues, according to Tanenbaum's book, are as follows. Of course these points are from his perspective and some others may have different opinions on this regard.
Operating systems have become very large programs: The size and complexity of programs have increased so bad that, no one person can sit and implement an operating system in a few months.
Operating systems have to deal with concurrency: With the current multi-core architectures we see today, operating systems have to handle multiple users and multiple devices at the same time, which makes the design way more complex and harder to maintain.
Operating systems have to deal with potentially hostile users: Security and privacy are two main factors that users prefer when it comes to a good operating system. There can be hostile users who may steal user programs or even hi-jack machines. Operating system designs have to incorporate these aspects in to their design process as well.
Anonymous and different users accessing computers today: Operating systems need to take measures to do proper file and resource sharing between multiple users. The management of sharing files is very hard when multiple users are accessing the same computing device.
Operating systems should be able to handle future hardware and software changes: Many operating systems that we see today have existed for decades. And with the changing world they have been well thought and designed with respect to future hardware and software changes. This is also a major design consideration.
Most operating systems do not have a specific type of users: When designing an operating system, we need to provide for a considerable generality, so that many users can use this. Even if you decide to target a specific user base, there should be different levels of users within that base. So there should be some level of generality in the design.
Operating systems should generally be portable: Portable means, it should work on different types of hardware and machines. There are certain operating systems which are designed specifically for certain kinds of machines. Instances like this are very rare, and most users prefer operating systems to be portable.
Operating systems should provide backward compatibility: New operating systems may have different restrictions on word lengths, file names and other aspects. But some applications and users are still stuck with the previous operating system designs, which shows the need for backward compatibility to older operating systems.
In my opinion I see a lot more reasons why operating system designing has become a very hard task over the years. These are different from what was mentioned before and designers do need to consider these as well.
Operating system interface design has become very complex: The interfaces that users require are different from each other. They should be simple, complete and efficient. There should be customizable interfaces and general interfaces to support different paradigms.
Designing operating systems to cater users as well as programmers: These two types of users need common functionality as well as different functionalities from operating systems. As an example, operating systems should provide features like suspending processes to programmers.
Designing newer systems which are better than the existing ones: Most operating system upgrades that we see today have only a few optimizations and User Interface changes. They are not really upgrades, but updates. This is where marketing should be strong, that they can sell newer systems over the older systems. Designers should adhere to this aspect as well, when designing operating systems.
Designing operating systems to be faster with faster hardware: MS-DOS and Unix Version 7 booted up in second. But today’s operating systems take huge amounts of time to boot. Even though the hardware is 10000 times faster, additional scans like bus scans, memory scans have to run at boot up, which makes the booting process slow in newer operating systems
Designing operating systems with the anticipation of future trends: You can never foresee the future, but trends can be analyzed beforehand. for example, networking, virtualization, distributed systems etc. In future, when it comes to networking, there will be no difference between local and cloud. People will feel that both are the same due to the latest networking technologies that we see today.
The level of testing on Functional and Nonfunctional requirements is getting complex: There are new requirements being added with every new operating system. Quality aspects such as reliability, user interfaces, security etc play a major role in operating systems. Developing these test cases is very tough and a lengthy process, where the ultimate goal is to make the operating system idiot proof in the worst case.
How to Design your Own Operating system
Now that we have a general idea on what operating systems are and how they work, let's look at how to develop and design our own operating system. These operating system design principles given below, are just basic guidelines on how to design your own operating system. The intention of presenting this in this blog is to give you a clear idea on how difficult the process is and to narrow it down into an abstract level, so that everyone can understand how this problem has been addressed.
1) Interface Design
Probably the best way to begin, is to think about the interfaces it should provide. By understanding the different levels of interfaces that should be provided, the designer will get an idea on what kind of functionalities should be provided to the general user. These interfaces can be categorized into two aspects. The first one is the system level interface design, and the next one is the user level interface design. As an example a developer might decide to install or write a new device driver. but a general user might just consider installing a simple application that will do everything he needs. So this is the level of abstraction that we need to consider when developing interfaces for operating systems.
According to Tanenbaum, There are three main operating system interface guiding principles.
Simplicity
Completeness
Efficiency
2) Paradigms
The next step in operating system designs, is to understand the different levels of paradigms that the operating system should provide for. This is where we need to distinguish between two kinds of operating system customers. The first type is the general user, and the other type is the developer. The three levels of Paradigms That we need to consider are as follows.
2.1 User interface Paradigm
This includes both user level interfaces as well as system call interfaces. Most operating system Paradigms are based on the WIMP Paradigm. WIMP stands for Windows Icons Menus and Pointers.
2.2 Execution Paradigm
The two levels of execution paradigms are Algorithmic Paradigms and Event Driven Paradigms. The algorithmic paradigm is based on a program that is known before or a program that runs based on parameters. Event Driven paradigms normally run when an event has occurred.
2.3 Data Paradigm
This explains the level of abstraction that should be provided for the data in the system. For different kinds of users, the operating system needs to provide and address different levels of data paradigms.
3) Implementation
Now that we have a clear Idea on operating system interfaces and Paradigms, next we will look at the implementation strategies that can be adopted by operating system designers.
3.1 System structure
This is the very first decision that designers have to take and which is also a very tricky decision. Given below are different kinds of system structures that designers use for operating systems.
Layered systems
Exo kernels
Microkernel based client server systems
Monolithic kernels
Extensible systems
Kernel threads
3.2 Mechanism versus Policy
Designer should be able to separate mechanisms from policies. This is by putting the mechanism in the operating system and leaving the policy to user processes.
3.3 Orthogonality
The ability to combine separate concepts independently is called orthogonality. This is to keep different kinds of concepts independent, so that they can be executed in an orderly manner, or can be replaced when needed.
3.4 Naming
Most operating system components like data structure have unique identifiers or names that we use. For example login name, file names, device names, process IDs, and so on. how these names are constructed and managed is an important issue in system design and implementation.
3.5 Binding time
According to the above section, different components have their own names. So, there should be a way for us to map with these names and the real components. This is where binding comes into place. There are two types of bindings. the first one is early binding which is simple but less flexible. The other one is late binding which is more complicated but often more flexible.
3.6 Static vs Dynamic Structures
When designing operating systems, it is important to identify what kind of data structures to be used. The static data structures are always simpler to understand, easier to program, and faster in use. Dynamic data structures become a little more complex, but it provides flexibility when executing the operating system functions.
3.7 Top down vs Bottom up implementation
In the top-down implementation, the designer starts with the system call handlers and see what mechanisms and data structures are needed to support them. Main problem with these approaches is that, it is very hard to test anything with only the top level procedures available. Therefore many developers and designers prefer to use the bottom up approach, where they can start coding from the low level hardware.
Summary
These are just basic guidelines for you to design your own operating system. Most of these principles were taken from the modern operating systems book mentioned above. Designing an Operating System starts with determining what it should do. This is why understanding the user interfaces at the beginning is important. It should have clear user interface paradigms, execution paradigms and data paradigms. The system should be well structured with a proper underlying architecture. The internal components of an operating system should be orthogonal to one another and should clearly separate policy from mechanism. Other concepts like naming, using data structures, binding time etc, should be decided accordingly.
References