寒假学习笔记1.19
一、 操作系统内核基础
-
内核架构与引导过程
引导加载器(Bootloader)
python
class Bootloader:
def init(self):
self.boot_sector_size = 512 # 传统MBR大小
self.boot_signature = 0xAA55 # 引导扇区签名
self.kernel_entry_point = Nonedef load_mbr(self, disk_image):
"""模拟BIOS加载MBR"""
# 检查引导签名
if disk_image[510] != 0x55 or disk_image[511] != 0xAA:
raise BootError("无效的引导扇区签名")# 读取引导代码 boot_code = disk_image[:446] # 读取分区表(简化,只处理一个活动分区) partition_table = disk_image[446:510] active_partition = None for i in range(0, len(partition_table), 16): entry = partition_table[i:i+16] if entry[0] == 0x80: # 活动分区 active_partition = { 'bootable': True, 'start_lba': int.from_bytes(entry[8:12], 'little'), 'sector_count': int.from_bytes(entry[12:16], 'little') } break if not active_partition: raise BootError("未找到活动分区") return active_partitiondef load_kernel(self, disk_image, start_lba, sector_count):
"""加载内核到内存"""
# 计算内核在磁盘映像中的位置
sector_size = 512
kernel_offset = start_lba * sector_size
kernel_size = sector_count * sector_sizeif kernel_offset + kernel_size > len(disk_image): raise BootError("内核超出磁盘范围") # 读取内核代码 kernel_code = disk_image[kernel_offset:kernel_offset + kernel_size] # 解析内核头部 kernel_header = self.parse_kernel_header(kernel_code) # 加载到内存 load_address = kernel_header['load_address'] code_size = kernel_header['code_size'] entry_point = kernel_header['entry_point'] # 将内核代码复制到内存 for i in range(min(code_size, len(kernel_code))): memory.write_byte(load_address + i, kernel_code[i]) self.kernel_entry_point = entry_point return entry_pointdef parse_kernel_header(self, kernel_code):
"""解析内核头部信息"""
# 假设内核头部格式:
# 0-3: 魔数 "KRNL"
# 4-7: 入口点
# 8-11: 加载地址
# 12-15: 代码大小
# 16-: 内核代码magic = kernel_code[0:4].decode('ascii', errors='ignore') if magic != 'KRNL': raise BootError("无效的内核魔数") return { 'magic': magic, 'entry_point': int.from_bytes(kernel_code[4:8], 'little'), 'load_address': int.from_bytes(kernel_code[8:12], 'little'), 'code_size': int.from_bytes(kernel_code[12:16], 'little') }def execute(self):
"""跳转到内核入口点"""
if self.kernel_entry_point is None:
raise BootError("内核未加载")# 设置CPU状态 cpu.registers['CS'] = 0x08 # 内核代码段选择子 cpu.registers['DS'] = 0x10 # 内核数据段选择子 cpu.registers['SS'] = 0x10 # 内核堆栈段选择子 cpu.registers['ESP'] = 0x90000 # 内核栈顶 cpu.registers['EIP'] = self.kernel_entry_point # 开启保护模式(简化) cpu.cr0 = 0x80000001 # 设置PE位和PG位 -
全局描述符表(GDT)与保护模式
python
class GlobalDescriptorTable:
def init(self):
self.gdt = []
self.gdtr = {'base': 0, 'limit': 0}
self.current_index = 0# 添加空描述符(索引0) self.add_descriptor(0, 0, 0, 0) # 内核代码段 self.kernel_code_segment = self.add_descriptor( base=0x00000000, limit=0xFFFFFFFF, access=0x9A, # 可执行,可读,DPL=0 flags=0xCF # 粒度=4KB,32位 ) # 内核数据段 self.kernel_data_segment = self.add_descriptor( base=0x00000000, limit=0xFFFFFFFF, access=0x92, # 可读可写,DPL=0 flags=0xCF ) # 用户代码段 self.user_code_segment = self.add_descriptor( base=0x00000000, limit=0xFFFFFFFF, access=0xFA, # 可执行,可读,DPL=3 flags=0xCF ) # 用户数据段 self.user_data_segment = self.add_descriptor( base=0x00000000, limit=0xFFFFFFFF, access=0xF2, # 可读可写,DPL=3 flags=0xCF ) # 任务状态段(TSS) self.tss_segment = Nonedef add_descriptor(self, base, limit, access, flags):
"""添加描述符到GDT"""
descriptor = GDTDescriptor()
descriptor.base = base
descriptor.limit = limit
descriptor.access = access
descriptor.flags = flagsself.gdt.append(descriptor) self.current_index += 1 return (self.current_index - 1) * 8 # 返回选择子def setup_tss(self, tss_address):
"""设置任务状态段"""
self.tss_segment = self.add_descriptor(
base=tss_address,
limit=103, # TSS大小
access=0x89, # 32位TSS,DPL=0
flags=0x00
)def load_gdtr(self):
"""加载GDTR寄存器"""
self.gdtr['base'] = id(self.gdt) # 简化:用ID作为地址
self.gdtr['limit'] = len(self.gdt) * 8 - 1
class GDTDescriptor:
"""GDT描述符"""
def init(self):
self.base = 0
self.limit = 0
self.access = 0
self.flags = 0
def encode(self):
"""编码为8字节"""
# 编码规则:
# 字节0-1: limit低16位
# 字节2-4: base低24位
# 字节5: access字节
# 字节6-7: limit高4位 + flags低4位 + base高8位
encoded = bytearray(8)
# limit低16位
encoded[0] = self.limit & 0xFF
encoded[1] = (self.limit >> 8) & 0xFF
# base低24位
encoded[2] = self.base & 0xFF
encoded[3] = (self.base >> 8) & 0xFF
encoded[4] = (self.base >> 16) & 0xFF
# access字节
encoded[5] = self.access
# limit高4位 + flags低4位
encoded[6] = ((self.limit >> 16) & 0x0F) | ((self.flags << 4) & 0xF0)
# base高8位
encoded[7] = (self.base >> 24) & 0xFF
return bytes(encoded)
二、 进程管理与调度
-
进程控制块扩展
python
class ProcessControlBlock:
def init(self, pid, name, priority=1):
self.pid = pid
self.name = name
self.priority = priority
self.state = 'NEW' # NEW, READY, RUNNING, BLOCKED, TERMINATED# 寄存器上下文 self.context = { 'eax': 0, 'ebx': 0, 'ecx': 0, 'edx': 0, 'esi': 0, 'edi': 0, 'ebp': 0, 'esp': 0, 'eip': 0, 'eflags': 0x202, # 中断启用 'cs': 0x1B, # 用户代码段选择子 (DPL=3) 'ds': 0x23, # 用户数据段选择子 (DPL=3) 'es': 0x23, 'fs': 0x23, 'gs': 0x23, 'ss': 0x23, } # 内存信息 self.page_directory = None self.memory_pages = [] # 分配的物理页列表 # 文件描述符 self.file_descriptors = [None] * 20 # 文件描述符表 self.file_descriptors[0] = stdin # 标准输入 self.file_descriptors[1] = stdout # 标准输出 self.file_descriptors[2] = stderr # 标准错误 # 进程关系 self.parent_pid = None self.children = [] self.exit_code = None # 资源使用 self.cpu_time = 0 self.memory_usage = 0 self.start_time = time.time() # 信号处理 self.signal_handlers = {} self.pending_signals = [] # 工作目录 self.working_directory = '/' # 用户和组 self.uid = 0 # root用户 self.gid = 0 self.euid = 0 # 有效用户ID # 能力集 self.capabilities = set() -
调度器扩展
python
class Scheduler:
def init(self):
self.processes = {} # pid -> PCB
self.ready_queue = [] # 就绪队列
self.blocked_queue = [] # 阻塞队列
self.current_pid = None
self.next_pid = 1000 # 从1000开始分配PID# 调度策略 self.scheduler_policy = 'RR' # Round Robin self.time_slice = 100 # 时间片(毫秒) self.ticks = 0 # 多级反馈队列 self.multi_level_queues = { 0: [], # 最高优先级,时间片最短 1: [], # 中等优先级 2: [], # 最低优先级,时间片最长 } self.priority_time_slices = {0: 50, 1: 100, 2: 200} # 统计信息 self.context_switches = 0 self.total_processes = 0 self.average_wait_time = 0def create_process(self, program_path, name=None, priority=1):
"""创建新进程"""
pid = self.next_pid
self.next_pid += 1if name is None: name = f"process_{pid}" # 创建PCB pcb = ProcessControlBlock(pid, name, priority) # 加载程序到内存 self.load_program(pcb, program_path) # 设置初始上下文 pcb.context['eip'] = pcb.entry_point pcb.context['esp'] = pcb.stack_top # 添加到就绪队列 self.processes[pid] = pcb self.ready_queue.append(pcb) # 更新统计 self.total_processes += 1 return piddef load_program(self, pcb, program_path):
"""加载程序到进程地址空间"""
# 读取可执行文件
with open(program_path, 'rb') as f:
exec_data = f.read()# 解析ELF头部(简化) if exec_data[0:4] != b'\x7fELF': raise LoadError("不是有效的ELF文件") # 分配内存页 code_pages = self.allocate_pages(pcb, 4) # 分配4页用于代码 data_pages = self.allocate_pages(pcb, 2) # 分配2页用于数据 stack_pages = self.allocate_pages(pcb, 1) # 分配1页用于栈 # 设置入口点和栈顶 pcb.entry_point = 0x08048000 # Linux默认的ELF入口地址 pcb.stack_top = 0xC0000000 - 4 # 栈顶(向下生长) # 复制代码和数据 self.copy_to_user_space(pcb, pcb.entry_point, exec_data)def schedule(self):
"""调度下一个进程"""
if not self.ready_queue and not self.multi_level_queues[0]:
return None# 根据调度策略选择下一个进程 if self.scheduler_policy == 'RR': return self.round_robin_schedule() elif self.scheduler_policy == 'MLFQ': return self.mlfq_schedule() elif self.scheduler_policy == 'PRIORITY': return self.priority_schedule() else: return self.round_robin_schedule()def round_robin_schedule(self):
"""轮转调度"""
if not self.ready_queue:
return None# 保存当前进程 if self.current_pid and self.current_pid in self.processes: current_pcb = self.processes[self.current_pid] if current_pcb.state == 'RUNNING': current_pcb.state = 'READY' self.ready_queue.append(current_pcb) # 选择下一个进程 next_pcb = self.ready_queue.pop(0) next_pcb.state = 'RUNNING' self.current_pid = next_pcb.pid # 更新统计 self.context_switches += 1 next_pcb.cpu_time += self.time_slice return next_pcbdef mlfq_schedule(self):
"""多级反馈队列调度"""
# 检查最高优先级队列
for level in range(3):
if self.multi_level_queues[level]:
# 保存当前进程
if self.current_pid and self.current_pid in self.processes:
current_pcb = self.processes[self.current_pid]
if current_pcb.state == 'RUNNING':
# 如果进程用完了时间片,降低优先级
if current_pcb.remaining_time <= 0:
current_pcb.priority = min(current_pcb.priority + 1, 2)
current_pcb.state = 'READY'
self.multi_level_queues[current_pcb.priority].append(current_pcb)# 选择下一个进程 next_pcb = self.multi_level_queues[level].pop(0) next_pcb.state = 'RUNNING' next_pcb.remaining_time = self.priority_time_slices[level] self.current_pid = next_pcb.pid self.context_switches += 1 return next_pcb return Nonedef timer_tick(self):
"""时钟中断处理"""
self.ticks += 1# 更新当前进程的时间片 if self.current_pid and self.current_pid in self.processes: pcb = self.processes[self.current_pid] pcb.remaining_time -= 1 # 如果时间片用完,强制调度 if pcb.remaining_time <= 0: self.schedule()def send_signal(self, pid, signal):
"""向进程发送信号"""
if pid not in self.processes:
return Falsepcb = self.processes[pid] pcb.pending_signals.append(signal) # 如果进程被阻塞,尝试唤醒 if pcb.state == 'BLOCKED' and signal in [signal.SIGCONT, signal.SIGUSR1]: self.unblock_process(pcb) return True -
虚拟内存管理
python
class VirtualMemoryManager:
def init(self):
# 页表结构
self.page_size = 4096 # 4KB页
self.page_directory = {} # 页目录
self.page_tables = {} # 页表# 物理内存管理 self.physical_pages = [] # 物理页帧列表 self.free_pages = [] # 空闲页帧 self.allocated_pages = {} # pid -> 页帧列表 # 页表缓存(TLB) self.tlb = {} self.tlb_hits = 0 self.tlb_misses = 0 # 页面置换算法 self.page_replacement_algorithm = 'LRU' # LRU, FIFO, CLOCKdef init_memory(self, total_memory):
"""初始化内存"""
total_pages = total_memory // self.page_size
self.physical_pages = [None] * total_pages # None表示空闲# 初始化空闲页列表 self.free_pages = list(range(total_pages)) # 分配内核空间 kernel_pages = 16 # 内核使用16个页 for i in range(kernel_pages): if self.free_pages: page_frame = self.free_pages.pop(0) self.physical_pages[page_frame] = 'KERNEL' # 设置内核页表 self.setup_kernel_page_table()def setup_kernel_page_table(self):
"""设置内核页表"""
# 内核空间:0x80000000以上
kernel_base = 0x80000000for i in range(1024): # 1MB内核空间 virtual_address = kernel_base + i * self.page_size physical_address = i * self.page_size # 恒等映射 self.map_page(0, virtual_address, physical_address, is_kernel=True, writable=True, executable=True)def create_address_space(self, pid):
"""为进程创建地址空间"""
if pid not in self.page_directory:
# 创建页目录
self.page_directory[pid] = {}# 分配页目录自身的页 pd_page = self.allocate_physical_page() self.page_directory[pid]['_pd_page'] = pd_page # 复制内核映射 self.copy_kernel_mappings(pid)def map_page(self, pid, virtual_addr, physical_addr,
is_kernel=False, writable=True, executable=False, user=True):
"""映射虚拟页到物理页"""
# 计算页目录索引和页表索引
pde_index = (virtual_addr >> 22) & 0x3FF # 10位
pte_index = (virtual_addr >> 12) & 0x3FF # 10位
offset = virtual_addr & 0xFFF # 12位# 获取或创建页表 if pid not in self.page_tables: self.page_tables[pid] = {} if pde_index not in self.page_tables[pid]: # 分配新页表 pt_page = self.allocate_physical_page() self.page_tables[pid][pde_index] = { 'page_frame': pt_page, 'entries': [None] * 1024 } # 创建页表项 pte = PageTableEntry() pte.present = 1 pte.writable = 1 if writable else 0 pte.user = 1 if user else 0 pte.executable = 1 if executable else 0 pte.page_frame = physical_addr // self.page_size # 存储页表项 self.page_tables[pid][pde_index]['entries'][pte_index] = pte # 更新TLB tlb_key = (pid, virtual_addr >> 12) # 按页对齐 self.tlb[tlb_key] = physical_addrdef translate_address(self, pid, virtual_addr):
"""地址转换(虚拟到物理)"""
# 检查TLB
tlb_key = (pid, virtual_addr >> 12)
if tlb_key in self.tlb:
self.tlb_hits += 1
physical_base = self.tlb[tlb_key]
return physical_base + (virtual_addr & 0xFFF)self.tlb_misses += 1 # 正常页表查找 pde_index = (virtual_addr >> 22) & 0x3FF pte_index = (virtual_addr >> 12) & 0x3FF offset = virtual_addr & 0xFFF if pid not in self.page_tables or pde_index not in self.page_tables[pid]: raise PageFaultError(f"页目录不存在: PID={pid}, PDE={pde_index}") pte = self.page_tables[pid][pde_index]['entries'][pte_index] if pte is None or not pte.present: raise PageFaultError(f"页面不存在: PID={pid}, VA=0x{virtual_addr:08X}") physical_base = pte.page_frame * self.page_size physical_addr = physical_base + offset # 更新TLB self.tlb[tlb_key] = physical_base return physical_addrdef handle_page_fault(self, pid, virtual_addr, error_code):
"""处理页错误"""
# 检查是否是写保护错误
is_write = (error_code & 0x02) != 0
is_user = (error_code & 0x04) != 0# 分配新物理页 physical_page = self.allocate_physical_page() if physical_page is None: # 需要页面置换 physical_page = self.page_replacement() # 清零新页面 self.zero_page(physical_page) # 建立映射 self.map_page(pid, virtual_addr, physical_page, user=is_user, writable=True) return Truedef page_replacement(self):
"""页面置换算法"""
if self.page_replacement_algorithm == 'LRU':
return self.lru_replacement()
elif self.page_replacement_algorithm == 'FIFO':
return self.fifo_replacement()
elif self.page_replacement_algorithm == 'CLOCK':
return self.clock_replacement()
else:
return self.lru_replacement()def lru_replacement(self):
"""LRU页面置换"""
# 找到最近最少使用的页面
lru_page = None
lru_time = float('inf')for pid in self.page_tables: for pde_index in self.page_tables[pid]: pt_info = self.page_tables[pid][pde_index] for pte_index, pte in enumerate(pt_info['entries']): if pte and pte.present and pte.recently_used: if pte.last_access_time < lru_time: lru_time = pte.last_access_time lru_page = (pid, pde_index, pte_index, pte) if lru_page: pid, pde_index, pte_index, pte = lru_page # 写回脏页 if pte.dirty: self.write_back_page(pid, pte.page_frame) # 清除映射 pte.present = 0 freed_page = pte.page_frame # 添加到空闲列表 self.free_pages.append(freed_page) return freed_page return None
class PageTableEntry:
"""页表项"""
def init(self):
self.present = 0 # 页面是否在内存中
self.writable = 0 # 是否可写
self.user = 0 # 用户模式访问
self.executable = 0 # 是否可执行
self.dirty = 0 # 是否被修改
self.accessed = 0 # 是否被访问
self.recently_used = 0 # 最近使用位(用于clock算法)
self.page_frame = 0 # 物理页帧号
self.last_access_time = 0 # 最后访问时间
三、 文件系统实现
-
虚拟文件系统(VFS)
python
class VirtualFileSystem:
def init(self):
self.root_fs = None
self.mounted_fs = {} # 挂载点 -> 文件系统
self.open_files = {} # 文件描述符 -> 文件对象
self.next_fd = 3 # 0,1,2已被标准流占用# 文件系统类型注册 self.fs_types = { 'ext2': Ext2FileSystem, 'fat32': FAT32FileSystem, 'tmpfs': TmpFileSystem, 'procfs': ProcFileSystem, }def mount(self, source, target, fs_type, options=None):
"""挂载文件系统"""
if target in self.mounted_fs:
raise MountError(f"挂载点 {target} 已在使用")if fs_type not in self.fs_types: raise MountError(f"不支持的文件系统类型: {fs_type}") # 创建文件系统实例 fs_class = self.fs_types[fs_type] fs_instance = fs_class(source, options) # 挂载 self.mounted_fs[target] = fs_instance # 如果是根文件系统 if target == '/': self.root_fs = fs_instance return Truedef open(self, pathname, flags, mode=0o666):
"""打开文件"""
# 解析路径
fs, real_path = self.resolve_path(pathname)
if fs is None:
raise FileNotFoundError(f"找不到文件: {pathname}")# 打开文件 file_obj = fs.open(real_path, flags, mode) # 分配文件描述符 fd = self.next_fd self.next_fd += 1 self.open_files[fd] = { 'file': file_obj, 'path': pathname, 'flags': flags, 'position': 0, 'fs': fs } return fddef read(self, fd, size):
"""从文件读取数据"""
if fd not in self.open_files:
raise BadFileDescriptorError(f"无效的文件描述符: {fd}")file_info = self.open_files[fd] file_obj = file_info['file'] position = file_info['position'] # 检查访问权限 if not (file_info['flags'] & os.O_RDONLY): raise PermissionError("文件未以读取模式打开") # 读取数据 data = file_obj.read(position, size) # 更新位置 file_info['position'] += len(data) return datadef write(self, fd, data):
"""向文件写入数据"""
if fd not in self.open_files:
raise BadFileDescriptorError(f"无效的文件描述符: {fd}")file_info = self.open_files[fd] file_obj = file_info['file'] position = file_info['position'] # 检查访问权限 if not (file_info['flags'] & os.O_WRONLY): raise PermissionError("文件未以写入模式打开") # 写入数据 bytes_written = file_obj.write(position, data) # 更新位置 file_info['position'] += bytes_written return bytes_writtendef close(self, fd):
"""关闭文件"""
if fd not in self.open_files:
raise BadFileDescriptorError(f"无效的文件描述符: {fd}")file_info = self.open_files[fd] file_obj = file_info['file'] # 关闭文件 file_obj.close() # 从打开文件表中移除 del self.open_files[fd] return Truedef resolve_path(self, pathname):
"""解析路径,返回文件系统和实际路径"""
# 规范化路径
normalized = os.path.normpath(pathname)# 查找最长的匹配挂载点 best_match = None best_fs = None for mount_point, fs in self.mounted_fs.items(): if normalized.startswith(mount_point): if best_match is None or len(mount_point) > len(best_match): best_match = mount_point best_fs = fs if best_fs is None: return None, None # 计算在文件系统中的实际路径 relative_path = normalized[len(best_match):] if not relative_path: relative_path = '/' return best_fs, relative_path
class Ext2FileSystem:
"""EXT2文件系统实现(简化版)"""
def init(self, device, options=None):
self.device = device
self.block_size = 4096
self.block_groups = []
self.inode_table = {}
self.superblock = None
# 读取超级块
self.read_superblock()
# 读取块组描述符表
self.read_block_group_descriptors()
def read_superblock(self):
"""读取超级块"""
# 超级块位于1024字节偏移处
superblock_data = self.read_block(1) # 第1个块(假设块大小>=1024)
self.superblock = Ext2Superblock()
self.superblock.decode(superblock_data)
# 计算块大小
self.block_size = 1024 << self.superblock.log_block_size
def open(self, path, flags, mode):
"""打开文件"""
# 查找inode
inode = self.lookup_path(path)
if inode is None:
# 如果文件不存在且需要创建
if flags & os.O_CREAT:
inode = self.create_file(path, mode)
else:
raise FileNotFoundError(f"文件不存在: {path}")
# 检查权限
if not self.check_permission(inode, flags):
raise PermissionError("权限不足")
return Ext2File(inode, self)
def lookup_path(self, path):
"""通过路径查找inode"""
components = path.strip('/').split('/')
if not components or components[0] == '':
# 根目录
return self.read_inode(2) # 根目录的inode编号通常是2
current_inode = self.read_inode(2)
for component in components:
# 在目录中查找条目
found = False
for entry in self.read_directory(current_inode):
if entry.name == component:
current_inode = self.read_inode(entry.inode)
found = True
break
if not found:
return None
return current_inode
def read_inode(self, inode_num):
"""读取inode"""
if inode_num in self.inode_table:
return self.inode_table[inode_num]
# 计算inode所在块组
block_group = (inode_num - 1) // self.superblock.inodes_per_group
index_in_group = (inode_num - 1) % self.superblock.inodes_per_group
# 读取inode表块
bg_desc = self.block_groups[block_group]
inode_table_block = bg_desc.inode_table_start
inode_offset = index_in_group * self.superblock.inode_size
block_index = inode_table_block + (inode_offset // self.block_size)
offset_in_block = inode_offset % self.block_size
block_data = self.read_block(block_index)
inode_data = block_data[offset_in_block:offset_in_block + self.superblock.inode_size]
# 解码inode
inode = Ext2Inode()
inode.decode(inode_data)
inode.inode_number = inode_num
self.inode_table[inode_num] = inode
return inode
class Ext2File:
"""EXT2文件对象"""
def init(self, inode, fs):
self.inode = inode
self.fs = fs
self.size = inode.size
self.blocks = self.get_blocks()
def read(self, position, size):
"""从指定位置读取数据"""
if position >= self.size:
return b''
# 限制读取大小
read_size = min(size, self.size - position)
# 计算起始块和偏移
start_block = position // self.fs.block_size
offset_in_block = position % self.fs.block_size
data = bytearray()
remaining = read_size
while remaining > 0:
# 获取物理块号
if start_block >= len(self.blocks):
break
physical_block = self.blocks[start_block]
# 读取块
block_data = self.fs.read_block(physical_block)
# 计算本次读取的大小
chunk_size = min(self.fs.block_size - offset_in_block, remaining)
# 复制数据
data.extend(block_data[offset_in_block:offset_in_block + chunk_size])
# 更新状态
remaining -= chunk_size
start_block += 1
offset_in_block = 0
return bytes(data)
四、 设备驱动程序
-
设备驱动框架
python
class DeviceDriver:
"""设备驱动基类"""
def init(self, name, device_id):
self.name = name
self.device_id = device_id
self.major = 0 # 主设备号
self.minor = 0 # 次设备号
self.status = 'UNINITIALIZED'
self.irq = None # 中断请求号
self.io_base = 0 # I/O基地址def init(self):
"""初始化设备"""
self.status = 'INITIALIZING'try: self._probe() self._setup() self.status = 'READY' return True except Exception as e: self.status = 'ERROR' print(f"设备 {self.name} 初始化失败: {e}") return Falsedef read(self, offset, size):
"""从设备读取数据"""
raise NotImplementedErrordef write(self, offset, data):
"""向设备写入数据"""
raise NotImplementedErrordef ioctl(self, command, arg):
"""设备控制"""
raise NotImplementedErrordef handle_interrupt(self):
"""处理中断"""
passdef _probe(self):
"""探测设备"""
passdef _setup(self):
"""设置设备"""
pass
class DeviceManager:
"""设备管理器"""
def init(self):
self.devices = {} # major:minor -> driver
self.char_devices = {} # 字符设备
self.block_devices = {} # 块设备
self.net_devices = {} # 网络设备
# 设备号分配
self.next_major = 1
# 注册标准设备
self.register_standard_devices()
def register_driver(self, driver):
"""注册设备驱动"""
# 分配设备号
if driver.major == 0:
driver.major = self.next_major
self.next_major += 1
# 生成设备标识
device_key = f"{driver.major}:{driver.minor}"
# 根据设备类型存储
if isinstance(driver, CharDeviceDriver):
self.char_devices[device_key] = driver
elif isinstance(driver, BlockDeviceDriver):
self.block_devices[device_key] = driver
elif isinstance(driver, NetworkDeviceDriver):
self.net_devices[device_key] = driver
self.devices[device_key] = driver
return device_key
def open_device(self, device_path):
"""打开设备文件"""
# 解析设备号
# 格式: /dev/xxx 或 major:minor
if ':' in device_path:
major, minor = map(int, device_path.split(':'))
device_key = f"{major}:{minor}"
else:
# 从/dev路径解析(简化)
if device_path == '/dev/tty':
device_key = "5:0" # 控制台
elif device_path == '/dev/sda':
device_key = "8:0" # 第一个SCSI磁盘
else:
raise DeviceNotFoundError(f"未知设备: {device_path}")
if device_key not in self.devices:
raise DeviceNotFoundError(f"设备未注册: {device_key}")
driver = self.devices[device_key]
# 打开设备
return driver.open()
def register_standard_devices(self):
"""注册标准设备"""
# 控制台设备
console_driver = ConsoleDriver()
console_driver.major = 5
console_driver.minor = 0
self.register_driver(console_driver)
# 空设备
null_driver = NullDeviceDriver()
null_driver.major = 1
null_driver.minor = 3
self.register_driver(null_driver)
# 零设备
zero_driver = ZeroDeviceDriver()
zero_driver.major = 1
zero_driver.minor = 5
self.register_driver(zero_driver)
-
具体设备驱动实现
python
class ConsoleDriver(CharDeviceDriver):
"""控制台驱动"""
def init(self):
super().init("console", "tty0")
self.input_buffer = []
self.output_buffer = []
self.cursor_x = 0
self.cursor_y = 0
self.video_memory = Nonedef _setup(self):
"""设置控制台"""
# 初始化视频内存
self.video_memory = bytearray(80 * 25 * 2) # 80x25文本模式# 清屏 self.clear_screen() # 设置光标位置 self.update_cursor()def clear_screen(self):
"""清屏"""
for i in range(0, len(self.video_memory), 2):
self.video_memory[i] = ord(' ')
self.video_memory[i + 1] = 0x07 # 灰色前景,黑色背景def write_char(self, char):
"""写入字符到控制台"""
if char == '\n':
self.cursor_x = 0
self.cursor_y += 1
elif char == '\r':
self.cursor_x = 0
elif char == '\t':
self.cursor_x = (self.cursor_x + 8) & ~7
elif char == '\b':
if self.cursor_x > 0:
self.cursor_x -= 1
else:
# 计算视频内存位置
pos = (self.cursor_y * 80 + self.cursor_x) * 2
if pos < len(self.video_memory):
self.video_memory[pos] = ord(char)
self.video_memory[pos + 1] = 0x07self.cursor_x += 1 # 检查是否需要滚动 if self.cursor_x >= 80: self.cursor_x = 0 self.cursor_y += 1 if self.cursor_y >= 25: self.scroll_screen() self.cursor_y = 24 self.update_cursor()def scroll_screen(self):
"""滚动屏幕"""
# 将第2-25行上移一行
for i in range(80 * 24):
src_pos = (i + 80) * 2
dst_pos = i * 2
self.video_memory[dst_pos] = self.video_memory[src_pos]
self.video_memory[dst_pos + 1] = self.video_memory[src_pos + 1]# 清空最后一行 last_line_start = 80 * 24 * 2 for i in range(0, 80 * 2, 2): self.video_memory[last_line_start + i] = ord(' ') self.video_memory[last_line_start + i + 1] = 0x07def update_cursor(self):
"""更新光标位置"""
# 在真实硬件中,这会通过I/O端口设置光标
passdef read(self, offset, size):
"""从控制台读取(非阻塞)"""
if not self.input_buffer:
return b''data = bytearray() while self.input_buffer and len(data) < size: char = self.input_buffer.pop(0) data.append(ord(char)) return bytes(data)def write(self, offset, data):
"""向控制台写入"""
for byte in data:
char = chr(byte)
self.write_char(char)return len(data)
class IDEHardDiskDriver(BlockDeviceDriver):
"""IDE硬盘驱动"""
def init(self, controller_base=0x1F0):
super().init("ide", "hda")
self.controller_base = controller_base
self.sector_size = 512
self.drive_number = 0 # 主设备
self.identify_data = None
def _probe(self):
"""探测IDE设备"""
# 发送IDENTIFY命令
self.write_port(6, 0xA0 | (self.drive_number << 4)) # 选择驱动器
self.write_port(7, 0xEC) # IDENTIFY命令
# 等待设备就绪
if not self.wait_ready():
return False
# 读取IDENTIFY数据
self.identify_data = bytearray(512)
for i in range(256):
data = self.read_port(0)
self.identify_data[i * 2] = data & 0xFF
self.identify_data[i * 2 + 1] = (data >> 8) & 0xFF
return True
def read_sector(self, lba, count=1):
"""读取磁盘扇区"""
if not self.identify_data:
raise DeviceError("设备未初始化")
sectors = []
for i in range(count):
sector = self._read_single_sector(lba + i)
sectors.append(sector)
return b''.join(sectors) if count > 1 else sectors[0]
def _read_single_sector(self, lba):
"""读取单个扇区"""
# 设置LBA地址
self.write_port(6, 0xE0 | (self.drive_number << 4) | ((lba >> 24) & 0x0F))
self.write_port(2, 1) # 扇区数
self.write_port(3, lba & 0xFF)
self.write_port(4, (lba >> 8) & 0xFF)
self.write_port(5, (lba >> 16) & 0xFF)
# 发送读命令
self.write_port(7, 0x20)
# 等待数据就绪
if not self.wait_data():
raise DeviceError("读取超时")
# 读取数据
sector_data = bytearray(self.sector_size)
for i in range(0, self.sector_size, 2):
data = self.read_port(0)
sector_data[i] = data & 0xFF
sector_data[i + 1] = (data >> 8) & 0xFF
return bytes(sector_data)
def write_port(self, reg, value):
"""写I/O端口"""
port = self.controller_base + reg
# 在真实系统中,这里会使用out指令
print(f"写入端口 0x{port:03X}: 0x{value:02X}")
def read_port(self, reg):
"""读I/O端口"""
port = self.controller_base + reg
# 在真实系统中,这里会使用in指令
# 返回模拟数据
return 0
def wait_ready(self):
"""等待设备就绪"""
for _ in range(1000):
status = self.read_port(7)
if not (status & 0x80): # 等待BSY位清除
return True
return False
五、 系统调用接口
-
系统调用表
python
class SystemCallTable:
"""系统调用表"""
def init(self):
self.syscalls = {}
self.syscall_numbers = {}# 注册系统调用 self.register_syscalls()def register_syscall(self, number, handler, name):
"""注册系统调用"""
self.syscalls[number] = handler
self.syscall_numbers[name] = numberdef register_syscalls(self):
"""注册所有系统调用"""
# 进程控制
self.register_syscall(1, self.sys_fork, "fork")
self.register_syscall(2, self.sys_exit, "exit")
self.register_syscall(3, self.sys_wait, "wait")
self.register_syscall(4, self.sys_execve, "execve")
self.register_syscall(5, self.sys_getpid, "getpid")# 文件操作 self.register_syscall(10, self.sys_open, "open") self.register_syscall(11, self.sys_read, "read") self.register_syscall(12, self.sys_write, "write") self.register_syscall(13, self.sys_close, "close") self.register_syscall(14, self.sys_lseek, "lseek") # 内存管理 self.register_syscall(20, self.sys_brk, "brk") self.register_syscall(21, self.sys_mmap, "mmap") self.register_syscall(22, self.sys_munmap, "munmap") # 进程间通信 self.register_syscall(30, self.sys_pipe, "pipe") self.register_syscall(31, self.sys_kill, "kill") self.register_syscall(32, self.sys_signal, "signal") # 系统信息 self.register_syscall(40, self.sys_gettimeofday, "gettimeofday") self.register_syscall(41, self.sys_uname, "uname")def dispatch(self, syscall_number, *args):
"""分发系统调用"""
if syscall_number not in self.syscalls:
return -errno.ENOSYS # 系统调用未实现try: handler = self.syscalls[syscall_number] result = handler(*args) return result except Exception as e: print(f"系统调用 {syscall_number} 错误: {e}") return -errno.EFAULTdef sys_fork(self):
"""创建新进程"""
current_pcb = scheduler.current_pcb# 复制进程 child_pid = scheduler.create_child_process(current_pcb) # 在子进程中返回0,在父进程中返回子进程PID return child_pid if current_pcb.pid != child_pid else 0def sys_exit(self, status):
"""进程退出"""
current_pcb = scheduler.current_pcb
current_pcb.exit_code = status
current_pcb.state = 'TERMINATED'# 通知父进程 if current_pcb.parent_pid: parent_pcb = scheduler.processes.get(current_pcb.parent_pid) if parent_pcb: # 如果父进程在等待,唤醒它 if parent_pcb.state == 'BLOCKED': scheduler.unblock_process(parent_pcb) # 释放资源 memory_manager.free_process_memory(current_pcb.pid) # 调度下一个进程 scheduler.schedule() # 这里永远不会返回 return 0def sys_open(self, pathname, flags, mode=0o666):
"""打开文件"""
try:
fd = vfs.open(pathname, flags, mode)
return fd
except FileNotFoundError:
return -errno.ENOENT
except PermissionError:
return -errno.EACCES
except Exception as e:
return -errno.EIOdef sys_read(self, fd, buf, count):
"""从文件描述符读取"""
try:
data = vfs.read(fd, count)# 将数据复制到用户空间 current_pcb = scheduler.current_pcb user_buffer = buf for i, byte in enumerate(data): if i >= count: break memory_manager.write_byte(user_buffer + i, byte) return len(data) except BadFileDescriptorError: return -errno.EBADF except Exception as e: return -errno.EIOdef sys_write(self, fd, buf, count):
"""向文件描述符写入"""
try:
# 从用户空间读取数据
current_pcb = scheduler.current_pcb
user_buffer = bufdata = bytearray() for i in range(count): byte = memory_manager.read_byte(user_buffer + i) data.append(byte) bytes_written = vfs.write(fd, bytes(data)) return bytes_written except BadFileDescriptorError: return -errno.EBADF except PermissionError: return -errno.EPERM except Exception as e: return -errno.EIO -
系统调用门
python
class SystemCallGate:
"""系统调用门"""
def init(self):
self.syscall_table = SystemCallTable()
self.sysenter_eip = 0 # SYSENTER入口点
self.sysenter_cs = 0 # SYSENTER代码段def setup_sysenter(self):
"""设置SYSENTER机制"""
# 设置MSR寄存器(在真实硬件中)
# WRMSR(0x174, 0x08) # SYSENTER_CS_MSR
# WRMSR(0x175, sysenter_eip) # SYSENTER_EIP_MSR
# WRMSR(0x176, sysenter_esp) # SYSENTER_ESP_MSR# 在我们的模拟器中,设置内部变量 self.sysenter_eip = id(self.handle_sysenter) self.sysenter_cs = 0x08 # 内核代码段def handle_interrupt_0x80(self, cpu_state):
"""处理int 0x80系统调用"""
# 获取系统调用号和参数
syscall_number = cpu_state.eax
arg1 = cpu_state.ebx
arg2 = cpu_state.ecx
arg3 = cpu_state.edx
arg4 = cpu_state.esi
arg5 = cpu_state.edi# 分发系统调用 result = self.syscall_table.dispatch(syscall_number, arg1, arg2, arg3, arg4, arg5) # 设置返回值 cpu_state.eax = result # 返回用户空间 return cpu_statedef handle_sysenter(self, cpu_state):
"""处理SYSENTER系统调用"""
# 保存用户栈
user_esp = cpu_state.esp
user_ss = cpu_state.ss# 切换到内核栈 cpu_state.esp = kernel_stack_top cpu_state.ss = 0x10 # 内核数据段 # 保存用户空间上下文 kernel_stack.push(user_esp) kernel_stack.push(user_ss) kernel_stack.push(cpu_state.eflags) kernel_stack.push(cpu_state.eip) # 返回地址 # 获取系统调用参数(从寄存器) syscall_number = cpu_state.eax arg1 = cpu_state.ebx arg2 = cpu_state.ecx arg3 = cpu_state.edx # 分发系统调用 result = self.syscall_table.dispatch(syscall_number, arg1, arg2, arg3) # 设置返回值 cpu_state.eax = result # 准备返回用户空间 cpu_state.eip = kernel_stack.pop() # 返回地址 eflags = kernel_stack.pop() user_ss = kernel_stack.pop() user_esp = kernel_stack.pop() # 恢复用户栈 cpu_state.esp = user_esp cpu_state.ss = user_ss cpu_state.eflags = eflags # 执行SYSEXIT(在真实硬件中) return cpu_state
六、 用户空间与Shell
-
用户程序加载器
python
class UserProgramLoader:
"""用户程序加载器"""
def init(self):
self.elf_parser = ELFParser()
self.library_loader = LibraryLoader()
self.dynamic_linker = DynamicLinker()def load_program(self, path, argv=None, envp=None):
"""加载并执行用户程序"""
# 读取可执行文件
with open(path, 'rb') as f:
elf_data = f.read()# 解析ELF文件 elf_info = self.elf_parser.parse(elf_data) # 检查架构 if elf_info.arch != 'i386': raise LoadError(f"不支持的架构: {elf_info.arch}") # 检查类型 if elf_info.type != 'EXEC' and elf_info.type != 'DYN': raise LoadError(f"不是可执行文件: {elf_info.type}") # 创建进程地址空间 pcb = self.create_process_address_space() # 加载段 self.load_segments(pcb, elf_info) # 处理重定位(如果是动态链接) if elf_info.is_dynamic: self.dynamic_linker.link(pcb, elf_info) # 设置堆栈 self.setup_stack(pcb, argv, envp) # 设置入口点 pcb.context['eip'] = elf_info.entry_point return pcbdef load_segments(self, pcb, elf_info):
"""加载程序段到内存"""
for segment in elf_info.segments:
if segment.type == 'LOAD':
# 计算内存权限
readable = segment.flags & 0x4
writable = segment.flags & 0x2
executable = segment.flags & 0x1# 分配内存页 pages = self.allocate_pages_for_segment(pcb, segment) # 复制数据 for i in range(segment.file_size): if i < len(segment.data): addr = segment.virtual_address + i byte = segment.data[i] memory_manager.write_byte_to_user(pcb.pid, addr, byte) # 对于.bss段,清零剩余部分 if segment.memory_size > segment.file_size: for i in range(segment.file_size, segment.memory_size): addr = segment.virtual_address + i memory_manager.write_byte_to_user(pcb.pid, addr, 0)def setup_stack(self, pcb, argv, envp):
"""设置用户栈"""
# 栈顶地址(假设为0xC0000000)
stack_top = 0xC0000000# 构建栈帧 # 从高地址向低地址生长 # 环境变量字符串 env_strings = [] env_pointers = [] if envp: for env in envp: env_strings.append(env.encode('utf-8') + b'\x00') # 参数字符串 arg_strings = [] arg_pointers = [] if argv: for arg in argv: arg_strings.append(arg.encode('utf-8') + b'\x00') # 计算总大小 total_size = 0 # 环境变量和参数字符串 for env in env_strings: total_size += len(env) for arg in arg_strings: total_size += len(arg) # 环境变量指针数组 total_size += (len(env_strings) + 1) * 4 # 包括null终止符 # 参数指针数组 total_size += (len(arg_strings) + 1) * 4 # 包括null终止符 # argc total_size += 4 # 对齐到16字节边界 total_size = (total_size + 15) & ~15 # 设置栈指针 stack_pointer = stack_top - total_size pcb.context['esp'] = stack_pointer # 写入栈数据 current_ptr = stack_pointer # 写入argc argc = len(arg_strings) memory_manager.write_dword_to_user(pcb.pid, current_ptr, argc) current_ptr += 4 # 写入argv指针 argv_ptr = current_ptr + (len(arg_strings) + 1) * 4 + (len(env_strings) + 1) * 4 arg_pointers_start = current_ptr for i in range(len(arg_strings)): memory_manager.write_dword_to_user(pcb.pid, current_ptr, argv_ptr) current_ptr += 4 # 写入参数字符串 for byte in arg_strings[i]: memory_manager.write_byte_to_user(pcb.pid, argv_ptr, byte) argv_ptr += 1 # 添加null终止符 memory_manager.write_byte_to_user(pcb.pid, argv_ptr, 0) argv_ptr += 1 # argv终止符null memory_manager.write_dword_to_user(pcb.pid, current_ptr, 0) current_ptr += 4 # 写入envp指针 envp_ptr = argv_ptr env_pointers_start = current_ptr for i in range(len(env_strings)): memory_manager.write_dword_to_user(pcb.pid, current_ptr, envp_ptr) current_ptr += 4 # 写入环境变量字符串 for byte in env_strings[i]: memory_manager.write_byte_to_user(pcb.pid, envp_ptr, byte) envp_ptr += 1 # 添加null终止符 memory_manager.write_byte_to_user(pcb.pid, envp_ptr, 0) envp_ptr += 1 # envp终止符null memory_manager.write_dword_to_user(pcb.pid, current_ptr, 0) current_ptr += 4 # 写入参数字符串 # 已经在上面的循环中写入 # 设置argv和envp寄存器(在某些调用约定中) pcb.context['ebx'] = arg_pointers_start -
简单Shell实现
python
class SimpleShell:
"""简单的命令行Shell"""
def init(self):
self.prompt = "$ "
self.current_dir = "/"
self.user = "user"
self.hostname = "localhost"
self.environment = {
'PATH': '/bin:/usr/bin',
'HOME': '/home/user',
'USER': self.user,
'SHELL': '/bin/sh',
'PWD': self.current_dir,
}# 内建命令 self.builtin_commands = { 'cd': self.cd_command, 'pwd': self.pwd_command, 'echo': self.echo_command, 'export': self.export_command, 'exit': self.exit_command, 'help': self.help_command, 'jobs': self.jobs_command, 'fg': self.fg_command, 'bg': self.bg_command, } # 作业控制 self.jobs = [] # 后台作业列表 self.current_job = Nonedef run(self):
"""运行Shell主循环"""
print(f"欢迎使用 SimpleShell v1.0")
print(f"输入 'help' 获取帮助")while True: try: # 显示提示符 prompt = self.get_prompt() line = input(prompt) # 解析命令 if not line.strip(): continue # 处理命令 self.execute_command(line) except KeyboardInterrupt: print("^C") continue except EOFError: print("\n退出") break except Exception as e: print(f"错误: {e}")def get_prompt(self):
"""生成提示符"""
# 格式: user@hostname:current_dir$
return f"{self.user}@{self.hostname}:{self.current_dir}{self.prompt}"def parse_command(self, line):
"""解析命令行"""
# 分割命令和参数
parts = self.split_line(line)
if not parts:
return None, []command = parts[0] args = parts[1:] # 处理重定向和管道 parsed = self.parse_redirections(args) return command, parseddef split_line(self, line):
"""分割命令行,处理引号"""
parts = []
current = ""
in_quote = None # ' 或 "
escape_next = Falsefor char in line: if escape_next: current += char escape_next = False elif char == '\\': escape_next = True elif in_quote: if char == in_quote: in_quote = None else: current += char elif char in ('\'', '"'): in_quote = char elif char in (' ', '\t'): if current: parts.append(current) current = "" else: current += char if current: parts.append(current) return partsdef parse_redirections(self, args):
"""解析重定向和管道"""
parsed = {
'command': None,
'args': [],
'stdin': None,
'stdout': None,
'stderr': None,
'append': False,
'background': False,
'pipe': None,
}i = 0 while i < len(args): arg = args[i] if arg == '<': # 输入重定向 if i + 1 < len(args): parsed['stdin'] = args[i + 1] i += 2 else: raise ParseError("输入重定向缺少文件名") elif arg == '>': # 输出重定向(覆盖) if i + 1 < len(args): parsed['stdout'] = args[i + 1] i += 2 else: raise ParseError("输出重定向缺少文件名") elif arg == '2>': # 错误重定向 if i + 1 < len(args): parsed['stderr'] = args[i + 1] i += 2 else: raise ParseError("错误重定向缺少文件名") elif arg == '>>': # 输出重定向(追加) if i + 1 < len(args): parsed['stdout'] = args[i + 1] parsed['append'] = True i += 2 else: raise ParseError("输出重定向缺少文件名") elif arg == '|': # 管道 if i + 1 < len(args): parsed['pipe'] = args[i + 1:] break else: raise ParseError("管道缺少命令") elif arg == '&': # 后台执行 parsed['background'] = True i += 1 else: if parsed['command'] is None: parsed['command'] = arg else: parsed['args'].append(arg) i += 1 return parseddef execute_command(self, line):
"""执行命令"""
command_info = self.parse_command(line)
if not command_info[0]:
returncommand, info = command_info # 检查是否是内建命令 if command in self.builtin_commands: self.builtin_commands[command](info) else: # 外部命令 self.execute_external_command(command, info)def execute_external_command(self, command, info):
"""执行外部命令"""
# 搜索可执行文件
executable_path = self.find_executable(command)
if not executable_path:
print(f"{command}: 命令未找到")
returntry: # 创建子进程 pid = scheduler.create_process(executable_path, argv=[command] + info['args']) if info['background']: # 后台执行 self.jobs.append({ 'pid': pid, 'command': command, 'args': info['args'], 'status': 'RUNNING' }) print(f"[{len(self.jobs)}] {pid}") else: # 前台执行 self.current_job = pid scheduler.wait_pid(pid) self.current_job = None except Exception as e: print(f"执行命令失败: {e}")def find_executable(self, command):
"""在PATH中查找可执行文件"""
# 如果是绝对路径或相对路径
if '/' in command:
if os.path.exists(command) and os.access(command, os.X_OK):
return command
return None# 在PATH中查找 path_dirs = self.environment.get('PATH', '').split(':') for dir_path in path_dirs: if not dir_path: continue full_path = os.path.join(dir_path, command) if os.path.exists(full_path) and os.access(full_path, os.X_OK): return full_path return None内建命令实现
def cd_command(self, info):
"""改变当前目录"""
if not info['args']:
target = self.environment.get('HOME', '/')
else:
target = info['args'][0]# 解析路径 if target.startswith('/'): new_dir = target else: new_dir = os.path.join(self.current_dir, target) # 规范化路径 new_dir = os.path.normpath(new_dir) # 检查目录是否存在 if os.path.isdir(new_dir): self.current_dir = new_dir self.environment['PWD'] = new_dir else: print(f"cd: {target}: 目录不存在")def echo_command(self, info):
"""回显参数"""
print(' '.join(info['args']))def exit_command(self, info):
"""退出Shell"""
code = 0
if info['args']:
try:
code = int(info['args'][0])
except ValueError:
print(f"exit: {info['args'][0]}: 需要数字参数")
returnraise SystemExit(code)
七、 综合示例:小型操作系统
-
内核初始化
python
class MicroKernel:
"""微型操作系统内核"""
def init(self):
# 初始化核心组件
self.gdt = GlobalDescriptorTable()
self.idt = InterruptDescriptorTable()
self.scheduler = Scheduler()
self.memory_manager = VirtualMemoryManager()
self.vfs = VirtualFileSystem()
self.device_manager = DeviceManager()
self.syscall_gate = SystemCallGate()# 系统状态 self.initialized = False self.running = False self.system_time = 0 # 内核线程 self.idle_thread = None self.kernel_threads = []def initialize(self):
"""初始化内核"""
print("正在初始化微型操作系统内核...")# 1. 初始化硬件抽象层 self.init_hardware() # 2. 初始化内存管理 self.init_memory() # 3. 初始化中断系统 self.init_interrupts() # 4. 初始化设备驱动 self.init_devices() # 5. 初始化文件系统 self.init_filesystem() # 6. 初始化进程管理 self.init_process_manager() # 7. 启动空闲线程 self.start_idle_thread() self.initialized = True print("内核初始化完成")def init_hardware(self):
"""初始化硬件"""
print(" 初始化硬件...")# 检测CPU self.detect_cpu() # 初始化时钟 self.init_clock() # 初始化控制台 self.init_console()def init_memory(self):
"""初始化内存管理"""
print(" 初始化内存管理...")# 假设有64MB物理内存 self.memory_manager.init_memory(64 * 1024 * 1024) # 初始化GDT self.gdt.load_gdtr() # 设置内核内存映射 self.setup_kernel_mappings()def init_interrupts(self):
"""初始化中断"""
print(" 初始化中断系统...")# 设置IDT self.idt.setup() # 注册中断处理程序 self.register_interrupt_handlers() # 开启中断 self.enable_interrupts()def init_devices(self):
"""初始化设备驱动"""
print(" 初始化设备驱动...")# 探测并初始化设备 self.device_manager.scan_devices() # 注册中断处理 for driver in self.device_manager.devices.values(): if driver.irq: self.idt.register_handler(driver.irq, driver.handle_interrupt)def init_filesystem(self):
"""初始化文件系统"""
print(" 初始化文件系统...")# 挂载根文件系统 root_device = self.device_manager.get_device_by_name("rootfs") if root_device: self.vfs.mount(root_device, '/', 'ext2') else: # 使用内存文件系统作为后备 self.vfs.mount(None, '/', 'tmpfs') # 创建必要的目录结构 self.create_default_directories()def create_default_directories(self):
"""创建默认目录结构"""
directories = [
'/bin', '/sbin', '/usr/bin', '/usr/sbin',
'/etc', '/home', '/root', '/tmp',
'/var', '/var/log', '/dev', '/proc',
'/sys', '/mnt', '/media',
]for directory in directories: try: self.vfs.mkdir(directory, 0o755) except: pass # 可能已存在def init_process_manager(self):
"""初始化进程管理"""
print(" 初始化进程管理...")# 创建init进程(PID=1) init_pid = self.scheduler.create_process("/sbin/init", "init", priority=0) if init_pid != 1: print("警告: init进程PID不是1")def start_idle_thread(self):
"""启动空闲线程"""
print(" 启动空闲线程...")# 创建空闲线程 self.idle_thread = KernelThread( name="idle", entry_point=self.idle_loop, priority=255 # 最低优先级 ) self.kernel_threads.append(self.idle_thread) self.idle_thread.start()def idle_loop(self):
"""空闲循环"""
while self.running:
# 执行HLT指令(在模拟器中休眠)
self.halt_cpu()# 检查是否有任务需要调度 if self.scheduler.ready_queue: self.scheduler.schedule()def halt_cpu(self):
"""暂停CPU(模拟)"""
time.sleep(0.001) # 休眠1毫秒def run(self):
"""运行内核"""
if not self.initialized:
self.initialize()self.running = True print("内核开始运行") try: # 内核主循环 while self.running: # 处理中断 self.handle_pending_interrupts() # 调度进程 next_process = self.scheduler.schedule() if next_process: self.context_switch(next_process) # 更新系统时间 self.system_time += 1 # 检查系统负载 self.check_system_load() except KeyboardInterrupt: print("\n收到关机信号") finally: self.shutdown()def shutdown(self):
"""关闭系统"""
print("正在关闭系统...")# 终止所有进程 for pid in list(self.scheduler.processes.keys()): if pid > 1: # 保留init进程 self.scheduler.terminate_process(pid) # 等待进程终止 time.sleep(0.1) # 卸载文件系统 self.vfs.umount_all() # 关闭设备 self.device_manager.shutdown_all() self.running = False print("系统关闭完成")def syscall_handler(self, syscall_number, *args):
"""系统调用处理入口"""
return self.syscall_gate.dispatch(syscall_number, *args)
class KernelThread:
"""内核线程"""
def init(self, name, entry_point, priority=1):
self.name = name
self.entry_point = entry_point
self.priority = priority
self.state = 'READY'
self.stack = bytearray(4096) # 4KB内核栈
self.registers = {}
def start(self):
"""启动内核线程"""
self.state = 'RUNNING'
# 设置初始寄存器
self.registers['eip'] = self.entry_point
self.registers['esp'] = id(self.stack) + len(self.stack) - 4
# 加入调度器
scheduler.add_kernel_thread(self)
-
启动与运行
python
def create_disk_image():
"""创建磁盘映像"""
print("创建磁盘映像...")创建空白磁盘映像
disk_size = 10 * 1024 * 1024 # 10MB
disk_image = bytearray(disk_size)创建MBR
mbr = create_mbr()
disk_image[0:512] = mbr创建分区表(一个分区)
partition_offset = 2048 * 512 # 从1MB开始
partition_size = 8 * 1024 * 1024 # 8MB分区表条目
partition_entry = bytearray(16)
partition_entry[0] = 0x80 # 可启动
partition_entry[4] = 0x83 # Linux分区类型
partition_entry[8:12] = (2048).to_bytes(4, 'little') # 起始LBA
partition_entry[12:16] = (partition_size // 512).to_bytes(4, 'little') # 扇区数写入分区表
disk_image[446:462] = partition_entry
创建文件系统
create_ext2_filesystem(disk_image[partition_offset:partition_offset+partition_size])
复制内核到文件系统
copy_kernel_to_fs(disk_image, partition_offset)
return bytes(disk_image)
def main():
"""主函数"""
print("=== 微型操作系统模拟器 ===")
# 创建磁盘映像
disk_image = create_disk_image()
# 创建引导加载器
bootloader = Bootloader()
# 加载MBR
try:
partition_info = bootloader.load_mbr(disk_image)
print(f"找到活动分区: LBA={partition_info['start_lba']}")
# 加载内核
entry_point = bootloader.load_kernel(
disk_image,
partition_info['start_lba'],
partition_info['sector_count']
)
print(f"内核加载完成,入口点: 0x{entry_point:08X}")
# 跳转到内核
bootloader.execute()
# 如果返回,说明内核已经初始化
print("正在启动内核...")
# 创建并运行内核
kernel = MicroKernel()
kernel.run()
except Exception as e:
print(f"启动失败: {e}")
return 1
return 0
if name == "main":
sys.exit(main())
浙公网安备 33010602011771号