Skip to content

Commit

Permalink
added hybrid kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohit MISHRA authored and Mohit MISHRA committed Oct 30, 2024
1 parent 5ebd620 commit 776ad38
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 329 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ An operating system (OS) serves as the fundamental bridge between computer hardw

System calls are the fundamental interface between an application and the operating system kernel. They provide a way for programs to request services from the operating system.

#### Categories of System Calls:
![history](./../images/systemArchOfKernelAndUserSpace.png)

### Categories of System Calls:

1. Process Control
- fork()
Expand Down
324 changes: 2 additions & 322 deletions Ch-2-OS-Architecture-Patterns/Introduction to OS Architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,7 @@ Operating system architecture represents the fundamental organization of system

The journey of operating system architecture spans several decades, marked by distinct evolutionary phases:

```mermaid
graph TB
Start[Early Computing Systems] --> A[First Generation OS]
A -->|Basic Batch Processing| B[Second Generation OS]
B -->|Multiprogramming| C[Third Generation OS]
C -->|Time Sharing| D[Modern OS Architectures]
D --> E[Monolithic Kernels]
D --> F[Microkernels]
D --> G[Hybrid Kernels]
D --> H[Exokernels]
E -->|Example| I[Linux]
F -->|Example| J[QNX]
G -->|Example| K[Windows NT]
H -->|Example| L[MIT Exokernel]
style Start fill:#f9f,stroke:#333
style D fill:#bbf,stroke:#333
```
![evolution](./../images/introToOS.png)

### First Generation (1945-1955)
In this era, there was no semblance of what we recognize as an operating system today. Computers required direct hardware manipulation, where programs were executed in isolation using manual operations via plugboards. This was the time of vacuum tube technology, where computing was a single-program affair, decidedly hands-on and rudimentary.
Expand Down Expand Up @@ -70,305 +51,4 @@ These core principles form the foundation for all major operating system archite
4. Optimizing system performance
5. Ensuring system reliability and security

The following chapters will explore how these principles are applied in different architectural patterns, with concrete examples and implementation details.

```mermaid
graph TD
A[User Applications] -->|System Calls| B[System Call Interface]
B --> C[Process Management]
B --> D[Memory Management]
B --> E[File System]
B --> F[Device Drivers]
B --> G[Network Stack]
C --> H[Hardware Abstraction Layer]
D --> H
E --> H
F --> H
G --> H
H --> I[CPU]
H --> J[Memory]
H --> K[Devices]
H --> L[Network Hardware]
subgraph Kernel Space
B
C
D
E
F
G
H
end
subgraph User Space
A
end
subgraph Hardware
I
J
K
L
end
```

### Basic Implementation Of Monolithic Kernel
```c
/* Basic implementation of a monolithic kernel's core components */

#include <stdint.h>
#include <stdbool.h>

/* Memory Management Structures */
typedef struct page {
uint32_t flags;
uint32_t ref_count;
struct page* next;
} page_t;

typedef struct {
page_t* free_pages;
uint32_t total_pages;
uint32_t used_pages;
} memory_manager_t;

/* Process Management Structures */
typedef enum {
PROCESS_READY,
PROCESS_RUNNING,
PROCESS_BLOCKED,
PROCESS_TERMINATED
} process_state_t;

typedef struct process {
uint32_t pid;
process_state_t state;
uint32_t* stack_pointer;
uint32_t* page_directory;
struct process* next;
} process_t;

typedef struct {
process_t* current_process;
process_t* process_list;
uint32_t next_pid;
} process_manager_t;

/* File System Structures */
typedef struct {
char name[256];
uint32_t size;
uint32_t permissions;
uint32_t inode;
} file_t;

typedef struct {
file_t* root_directory;
uint32_t total_files;
} filesystem_t;

/* Global Kernel State */
typedef struct {
memory_manager_t* memory_manager;
process_manager_t* process_manager;
filesystem_t* filesystem;
bool interrupts_enabled;
} kernel_t;

/* Memory Management Implementation */
void* allocate_page(memory_manager_t* mm) {
if (!mm->free_pages) {
return NULL; // Out of memory
}

page_t* page = mm->free_pages;
mm->free_pages = page->next;
mm->used_pages++;

page->ref_count = 1;
page->flags = 0;
page->next = NULL;

return (void*)page;
}

void free_page(memory_manager_t* mm, void* page_addr) {
page_t* page = (page_t*)page_addr;

if (page->ref_count > 0) {
page->ref_count--;
if (page->ref_count == 0) {
page->next = mm->free_pages;
mm->free_pages = page;
mm->used_pages--;
}
}
}

/* Process Management Implementation */
process_t* create_process(process_manager_t* pm) {
process_t* process = (process_t*)allocate_page(pm->current_process->page_directory);
if (!process) {
return NULL;
}

process->pid = pm->next_pid++;
process->state = PROCESS_READY;
process->stack_pointer = NULL; // Will be initialized during context switch
process->page_directory = NULL; // Will be set up by memory management

// Add to process list
process->next = pm->process_list;
pm->process_list = process;

return process;
}

void schedule_next_process(process_manager_t* pm) {
process_t* current = pm->current_process;

// Simple round-robin scheduling
if (current->next) {
pm->current_process = current->next;
} else {
pm->current_process = pm->process_list;
}

// Perform context switch
switch_context(current, pm->current_process);
}

/* Context Switching (Assembly implementation would be required) */
extern void switch_context(process_t* old, process_t* new);

/* System Call Handler */
void handle_system_call(uint32_t syscall_number, void* params) {
switch (syscall_number) {
case SYS_ALLOCATE_MEMORY:
// Handle memory allocation
break;
case SYS_CREATE_PROCESS:
// Handle process creation
break;
case SYS_READ_FILE:
// Handle file operations
break;
default:
// Handle unknown system call
break;
}
}

/* Interrupt Handler */
void interrupt_handler(uint32_t interrupt_number) {
// Save current process state

switch (interrupt_number) {
case TIMER_INTERRUPT:
// Handle timer interrupt
schedule_next_process(kernel.process_manager);
break;
case KEYBOARD_INTERRUPT:
// Handle keyboard interrupt
break;
case PAGE_FAULT:
// Handle page fault
break;
default:
// Handle unknown interrupt
break;
}

// Restore process state
}

/* Kernel Initialization */
void init_kernel() {
// Initialize memory management
kernel.memory_manager = (memory_manager_t*)KERNEL_MEMORY_START;
kernel.memory_manager->free_pages = (page_t*)MEMORY_START;
kernel.memory_manager->total_pages = TOTAL_MEMORY_PAGES;
kernel.memory_manager->used_pages = 0;

// Initialize process management
kernel.process_manager = (process_manager_t*)allocate_page(kernel.memory_manager);
kernel.process_manager->next_pid = 1;
kernel.process_manager->current_process = NULL;
kernel.process_manager->process_list = NULL;

// Initialize file system
kernel.filesystem = (filesystem_t*)allocate_page(kernel.memory_manager);
kernel.filesystem->root_directory = NULL;
kernel.filesystem->total_files = 0;

// Set up interrupt handlers
setup_interrupt_handlers();

// Enable interrupts
kernel.interrupts_enabled = true;
enable_interrupts();
}
```
Let me explain the key aspects of the monolithic kernel implementation:
### Core Components:
- **Memory Manager**: This component is tasked with the fundamental responsibilities of allocating and deallocating memory pages. It ensures that each process receives the memory it needs while also managing memory when processes terminate or when memory needs to be swapped out to disk, keeping the system's memory use efficient.
- **Process Manager**: Central to the operating system's functionality, the process manager oversees the lifecycle of processes from creation to termination. It schedules processes using various algorithms, ensuring fair access to CPU time and handling inter-process communication and synchronization.
- **File System**: Provides the necessary structure for storing, organizing, retrieving, and managing files on storage devices. This component implements basic operations for file manipulation, offering a hierarchical organization system for data.
- **Interrupt Handler**: Critical for real-time responsiveness, this component manages interrupts from hardware or software. It decides how to prioritize these interrupts, schedules the appropriate responses, and ensures that the system can react promptly to external events or internal conditions.
### Key Features:
- **Simple Page-based Memory Management**: Utilizes a straightforward approach where memory is divided into fixed-size pages, simplifying allocation and reducing fragmentation, although potentially less efficient in memory utilization compared to more complex schemes.
- **Round-robin Process Scheduling**: A scheduling algorithm where each process is given a fixed time slice to execute in a cyclic manner. This ensures that all processes get an equal opportunity to run, which is particularly useful in time-sharing systems.
- **Basic System Call Interface**: Offers a set of functions through which user programs can request services from the kernel, like file operations or process control, providing a controlled pathway for interaction between user space and kernel space.
- **Interrupt Handling Framework**: A structured approach to manage interrupts, allowing the OS to respond to various events by temporarily suspending one process to execute an interrupt service routine, thereby maintaining system stability and performance.
### Architecture Highlights:
```mermaid
graph TB
subgraph User_Space
A[User Applications]
B[System Libraries]
end
subgraph Kernel_Space
C[System Call Interface]
D[Process Management]
E[Memory Management]
F[File System]
G[Device Drivers]
H[Network Stack]
end
A -->|System Calls| B
B -->|API Calls| C
C --> D & E & F & G & H
D <--> E
E <--> F
F <--> G
G <--> H
style User_Space fill:#f0f0f0
style Kernel_Space fill:#d0d0d0
```

- **All Kernel Services Run in Kernel Space**: This design choice ensures that critical operations are protected from direct user interference, enhancing security but requiring context switches for user-level operations, which can impact performance due to the overhead involved.

- **Direct Function Calls Between Components**: Components within the kernel communicate directly through function calls rather than through message passing or other indirect methods, promoting efficiency but potentially reducing modularity.

- **Shared Kernel Memory Space**: All kernel components access a common memory area. This facilitates direct data sharing among kernel subsystems but requires careful synchronization to avoid conflicts.

- **Tightly Coupled Components**: The integration of kernel components in a monolithic architecture means they are highly interdependent. While this can lead to performance benefits due to direct interaction, it also means that changes in one part of the kernel might require significant adjustments elsewhere, complicating maintenance and expansion.
The following chapters will explore how these principles are applied in different architectural patterns, with concrete examples and implementation details.
Loading

0 comments on commit 776ad38

Please sign in to comment.