- We use C because developing an OS requires a very precise control of the generated code and direct access to memory.
- Booting an operating system consists of transferring control along a chain of small programs, each one more "powerful" than the previous one, where the operating system is the last "program".
- When the PC is turned on, the computer will start a small program that adheres to the Basic Input Output System (BIOS) standard. This program is usually stored on a read only memory chip on the motherboard of the PC.
- Modern operating systems do not use the BIOS functions, they use drivers that interact directly with the hardware, bypassing the BIOS.
- The BIOS program will transfer control of the PC to a program called a bootloader. The bootloader's task is to transfer control to us, the operating system developers, and our code.
- The bootloader will transfer control to the operating system by jumping to a position in memory.
- Assembly is very good for interacting with the CPU and enables maximum control over every aspect of the code. However, C is a much more convenient language to use. Therefore, we would like to use C as much as possible and use assembly code only where it makes sense.
- One prerequisite for using C is a stack, since all non-trivial C programs use a stack. Setting up a stack is not harder than to make the esp register point to the end of an area of free memory that is correctly aligned.
- When compiling the C code for the OS, a lot of flags to GCC need to be used. This is because the C code should not assume the presence of a standard library, since there is no standard library available for our OS.
- There are usually two different ways to interact with the hardware, memory-mapped I/O and I/O ports.
- If the hardware uses memory-mapped I/O then you can write to a specific memory address and the hardware will be updated with the new data.
- If the hardware uses I/O ports then the assembly code instructions out and in must be used to communicate with the hardware.
- The frame-buffer is a hardware device that is capable of displaying a buffer of memory on the screen.
- When data is transmitted via the serial port it is placed in buffers, both when receiving and sending data. This way, if you send data to the serial port faster than it can send it over the wire, it will be buffered.
- When paging is disabled, then the linear address space is mapped 1:1 onto the physical address space., and the physical memory can be accessed.
- To enable segmentation you need to set up a table that describes each segment--a segment descriptor table.
- The operating system must be able to handle interrupts in order to read information from the keyboard.
- Interrupts are handled via the Interrupt Descriptor Table (IDT). The IDT describes a handler for each interrupt. The interrupts are numbered and the handler for interrupt i is defined at the ith position in the table.
- When an interrupt occurs the CPU will push some information about the interrupt onto the stack, then look up the appropriate interrupt handler in the IDT and jump to it.
- The interrupt handler has to be written in assembly code, since all registers that the interrupt handlers use must be preserved by pushing them onto the stack. This is because the code that was interrupted doesn't know about the interrupt and will therefore expect that its registers stay the same.
- To start using hardware interrupts you must first configure the Programmable Interrupt Controller (PIC). The PIC makes it possible to map signals from the hardware to interrupts.
- Every interrupt from the PIC has to be acknowledge--that is, sending a message to the PIC confirming that the interrupt has been handled. If this isn't done the PIC won't generate any more interrupts.
- Virtual memory is an abstraction of physical memory. The purpose of virtual memory is generally to simplify application development and to let processes address more memory than what is actually physically present in the machine.
- Managing memory is a big part of what an operating system does.
- Segmentation translates a logical address into a linear address. Paging translates these linear addresses onto the physical address space, and determines access rights and how the memory should be cached.
- Paging is the most common technique used in x86 to enable virtual memory.
- The simplest kind of paging is when we map each virtual address onto the same physical address, called identity paging.
- Preferably, the kernel should be placed at a very high virtual memory address.
- Paging enables two things that are good for virtual memory. First, it allows for fine-grained access control to memory. Second, it creates the illusion of contiguous memory.
- A virtual file system (VFS) creates an abstraction on top of the concrete file systems. A VFS mainly supplies the path system and file hierarchy, it delegates operations on files to the underlying file systems.
- System calls is the way user-mode applications interact with the kernel--to ask for resources, request operations to be performed, etc. The system call API is the part of the kernel that is most exposed to the users, therefore its design requires some thought.
- System calls are traditionally invoked with software interrupts. The user applications put the appropriate values in registers or on the stack and then initiates a pre-definied interrupt which transfers execution to the kernel. The interrupt number used is dependent on the kernel.
- Creating new processes is usually down with two different system calls: fork and exec. fork creates an exact copy of the currently running process, while exec replaces the current process with one that is specified by a path to the location of a program in the file system.
- The easiest way to achieve rapid switching between processes is if the processes themselves are responsible for the switching. The processes run for a while and then tell the OS (via a system call) that it can now switch to another process. Giving up the control of CPU to another process is called yielding scheduling, since all the processes must cooperate with each other.
- Since cooperative scheduling is deterministic, it is much easier to debug than preemptive scheduling.
20180126
The little book about OS development by Erik Helin & Adam Renberg
The little book about OS development
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment