Introduction to Operating Systems-II

Parth Singh
6 min readJul 29, 2021

Getting to know the Operating System

Hey, there! you still around? Let’s continue our journey and dive deeper to understand the underlying principles and working of an Operating System. But, first if you have somehow jumped🪂 right on here, I would recommend you to have a look at my first blog here.

Now, since we have basic knowledge of the functionalities of an Operating System, let’s see how the gears turn together. But first, it is important to know that there are majorly three types of operating systems:

  1. Monolithic OS: Everything is available here on the OS, the file systems, device drivers, address spaces etc. So indeed this one is bulky and has downgraded performance. For example, this type of OS might implement two file systems, one for sequential access of files and one for unstructured and random I/O operations (like in a database we can select data in a non-sequential order).
  2. Modular OS: this OS implements basic functionalities and interfaces for extended capabilities, has better performance than monolithic type and has a smaller code base. But, is more prone to errors as the extended functionalities are added through modules at the system run time.
  3. Micro OS: also known as the Micro-Kernel is essentially designed for microcontrollers which are designed to work on specific hardware. Here, only the most basic programs like Inter-Process Communications, Address Spaces and threads are maintained by the OS.

Now, lets hop onto today’s main topic.

Processes and Process Management

Simply put, any program that is loaded in the memory becomes a process. To understand how a process is created , let’s have a look at what a Process Control Block is. “A Process Control Block is a data structure maintained by the Operating System for every process. A PCB keeps all the information needed to keep track of a process”. There are mainly two mechanisms by which a process can be created. In both mechanisms, a parent PCB creates a child PCB (you can draw an analogy to a family tree here ), the main difference between the two mechanisms lies in how the child PCB behaves.

fork(): Copies the parent PCB into the new child PCB. The child PCB continues to execute from where the parent PCB called it.

exec(): Replaces the child PCB with a new program. It’s execution begins from the starting of the code.

After the creation of the process it is given an address space(a location in the memory)which is broken into four parts -stack, heap, data and text.

Address Space for a Process

Text is the activity which is to be performed and data is the part which contains all the variables. The heap is the part which dynamically allocates memory for the process on the run time. While the Stack consists of the methods/functions and the return addresses and is responsible to carry out the process. As you might know Stack is a LIFO (Last in First Out) data structure, which is exactly what we need. For example, assume a process(X) that invokes another process(Y) for its completion, then we would want ‘Y’ to finish first so that ‘X’ can be completed, taking a look from the perspective of Stacks- the operations are:
PUSH(X) ->PUSH(Y) -> POP() -> POP().

When a process is under execution, it can be in any of the following states: New, Ready, Running, Waiting or Terminated.

Lifecycle of a Process

Every process in the beginning is in the new state, in which the OS checks if the process should be allowed to get executed and also allocates initial resources for the process. It is then admitted to the ready state, which as the name suggests is prepares the process to get executed. (Ya, I know that wasn’t an explanation 😅 but the process just waits here for a while so that there are ample resources for it to run) After this, the CPU scheduler assigns the process for execution. When the process requires an I/O operation, the process moves from the running state to the waiting state, where the I/O operation is completed and the process is sent back again to the ready state. You should take a moment to notice that I/O operations generally take much more time rather than the execution of the program itself and hence the CPU can execute another process in the meantime. After the process is completed, it is assigned a terminated state where it waits to be removed from the main memory. Another path is taken when a process takes more time than assigned by the CPU Scheduler (we call this time slice expiry), the process is then interrupted and sent back to the ready state, its current context is saved and another process is dispatched for execution and the cycle continues. Remember that this is an over-simplified version of how Processes are executed and modern Operating Systems follow lot more complex procedures to execute programs. But, I believe this much is fine for now.

Process Scheduling

Process scheduling is an essential part of any modern OS. Such multi-programming operating systems allow different processes to get loaded into the memory at a time and the loaded processes shares the CPU. The Operating System maintains all PCBs in Queues. The OS maintains a separate queue for each of the process states and PCBs of all processes in the same execution state are placed in the same queue.

Process Scheduling Queue

When the CPU scheduler switches the CPU from executing one process to execute another, the state from the current running process is stored into the process control block. After this, the state for the process to run next is loaded from its own PCB. Now, the second process can start its execution. This is an intuitive idea how the Scheduler works.

Inter-Process Communications

We now know how processes are executed inside the CPU, but every now and then a process requires assistance from many other processes, these processes are known as Co-operating Processes. You might wonder that Co-operating processes might be slower than the independent ones, but in reality these processes increase computational speed and make debugging easier(as the processes are now modular). To achieve this, Inter-process communications come into the picture. They are basically a mechanism by which processes can interact with each other and synchronize their actions towards reaching a specific goal. There are two methods by which processes can interact.

1. Message Passing

  • Establishes a link between the processes so that they can interact.
  • Exchanging messages/ commands:

1) send(message, destination)
2) receive(message, host)

Generally, in this method messages are sent using FIFO (Queue) Style.

2. Shared Memory

  • The two processes shares a common space or memory location known as buffer
  • Items produced by the Producer process are stored and from here the Consumer process consumes the item.

For a more illustrative figure you can have look below.

Shared Memory IPC

So, that’s all for today. I hope you are eagerly learning about Operating Systems with me on this journey. Although we haven’t started to apply our newly acquired knowledge to code anything, but bear with me as without this theoretical knowledge we would just be Penguins trying to fly! 😁
I am attaching a few references which I would recommend you to go through for a better understanding of these concepts.

In the next blog we would start coding a bit and get our hands dirty with the Shell and learn about threads and concurrency, coming an inch closer to making our very own Operating System from Scratch.

Until next time
Parth

Resources and References

--

--

Parth Singh

Undergraduate Student at IIT Roorkee. Pursuing Electronics and Communication Engineering