# CNK **Repository Path**: cnos1/cnk ## Basic Information - **Project Name**: CNK - **Description**: CNOS的开源内核,闭源版也使用同样内核 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-05-04 - **Last Updated**: 2026-05-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # CNOS Kernel Architecture ## 概述 CNOS是一个64位微内核操作系统,采用完全解耦架构。内核仅通过KAL(Kernel Abstraction Layer)与用户态通信,实现了内核与用户态的完全分离。 ## 目录结构 ``` kernel/ ├── main.c # 内核入口点 ├── entry.asm # 内核入口汇编 ├── interrupts.asm # 中断处理汇编 ├── io.h # IO端口操作宏定义 ├── pmm.h/c # 物理内存管理 ├── vmm.h/c # 虚拟内存管理 ├── idt.h/c # 中断描述符表 ├── isr.c # 中断服务程序 ├── process.h/c # 进程/调度管理 ├── ipc.h/c # 进程间通信 ├── multiboot.h/c # Multiboot协议支持 ├── shell.h/c # 内核Shell ├── gui.h # GUI接口 ├── cnos_syscall.h # 系统调用头文件 └── drivers/ # 驱动程序 ├── ata.h/c # ATA存储驱动 ├── vga.h/c # VGA文本驱动 ├── serial.h/c # 串口驱动 ├── graphics.h/c # 图形驱动接口 ├── mouse.h/c # PS/2鼠标驱动 ├── sheet.h/c # 图层管理 ├── font.h/c # 字体渲染 ├── pci.h/c # PCI总线驱动 ├── qemu_bga.h/c # QEMU BGA帧缓冲驱动 ├── intel_hd5500.h/c # Intel HD5500驱动 └── virtio_*/ # VirtIO驱动(网络、GPU、9P) ``` ## 启动流程 ``` BIOS/UEFI → Multiboot2 Header → entry.asm ↓ kernel_main(mbi_phys, boot_magic) ├── serial_init() # 初始化串口 ├── multiboot_validate() # 验证multiboot信息 ├── pmm_init() # 初始化物理内存管理 ├── vmm_init() # 初始化虚拟内存管理 ├── vga_init() # 初始化VGA文本模式 ├── 图形初始化 # intel_hd5500/qemu_bga/GRUB FB ├── ata_init_primary_master() # 初始化ATA存储 ├── vfs_init() # 初始化VFS(lwext4) ├── vfs_mount_root() # 挂载根文件系统 ├── process_init() # 初始化进程管理 ├── idt_init() # 初始化中断描述符表 ├── tss_init() # 初始化TSS └── sti; halt # 开启中断,进入空闲循环 ``` ## 核心组件 ### 1. 物理内存管理 (pmm) 物理内存管理器采用位图算法管理物理内存。 **主要接口:** - `pmm_init(mbi_phys)` - 从multiboot获取内存信息并初始化 - `pmm_alloc()` - 分配一个4KB页 - `pmm_free(void *addr)` - 释放一个4KB页 - `pmm_get_total_memory()` - 获取总内存大小 - `pmm_get_free_memory()` - 获取空闲内存大小 ### 2. 虚拟内存管理 (vmm) 基于x86-64分页的虚拟内存管理,支持1GB huge pages。 **主要接口:** - `vmm_init()` - 初始化页表结构 - `vmm_map(uint64_t virt, uint64_t phys, uint64_t flags)` - 映射虚拟地址到物理地址 - `vmm_unmap(uint64_t virt)` - 取消映射 - `vmm_alloc_range(uint64_t start, uint64_t end, uint64_t flags)` - 在指定范围分配 **页表标志:** - `VMM_PRESENT` - 页存在 - `VMM_RW` - 可写 - `VMM_USER` - 用户态可访问 - `VMM_HUGE` - Huge page (2MB/1GB) ### 3. 进程管理 (process) 支持多任务调度,采用轮转调度算法。 **进程控制块 (proc_t):** ```c typedef struct proc { uint64_t pid; // 进程ID uint64_t parent_pid; // 父进程ID proc_state_t state; // 进程状态 uint64_t rsp; // 内核栈指针 uint8_t *stack_base; // 栈底 uint32_t kernel_stack_sz; // 栈大小 uint8_t *user_stack_base; // 用户栈 uint64_t pml4_phys; // 页表物理地址 message_t msg_buffer; // IPC消息缓冲 struct proc *next_in_queue; struct proc *sender_queue; uint8_t home_core; void *newlib_reent_ctx; int exit_code; int waited; } proc_t; ``` **进程状态:** - `PROC_STATE_FREE` - 空闲槽位 - `PROC_STATE_READY` - 就绪 - `PROC_STATE_RUNNING` - 运行中 - `PROC_STATE_SENDING` - 发送消息中 - `PROC_STATE_RECEIVING` - 接收消息中 - `PROC_STATE_SLEEPING` - 睡眠 - `PROC_STATE_EXITED` - 已退出 **主要接口:** - `process_init()` - 初始化进程调度器 - `process_create(void (*entry)(void))` - 创建内核线程 - `process_create_user(void (*entry)(void))` - 创建用户进程 - `schedule()` - 调度下一个进程 - `process_getpid()` - 获取当前进程ID - `process_exit_current(int code)` - 退出当前进程 - `process_waitpid(int pid, int *status)` - 等待进程退出 ### 4. 中断处理 (idt/isr) **中断描述符表 (idt):** - 支持256个中断描述符 - 支持用户态中断(INT 0x80系统调用) **中断服务程序 (isr):** - 定时器中断 (IRQ 0) - 调度器触发 - 键盘中断 (IRQ 1) - PS/2键盘输入 - 鼠标中断 (IRQ 12) - PS/2鼠标 - 硬盘中断 (IRQ 14/15) - ATA控制器 - 系统调用 - 用户态请求 **主要接口:** - `idt_init()` - 初始化IDT - `irq_register(int irq, void (*handler)(void))` - 注册中断处理 - `kbd_pop_char_nonblock()` - 非阻塞获取键盘字符 - `gui_kbd_pop_char_nonblock()` - GUI模式键盘输入 ### 5. 进程间通信 (ipc) 基于消息的进程间通信机制。 **消息结构:** ```c typedef struct { int src_pid; int dst_pid; uint64_t type; uint64_t data[6]; } message_t; ``` **主要接口:** - `ipc_send(int dst, message_t *msg)` - 发送消息 - `ipc_recv(int src, message_t *msg)` - 接收消息 - `ipc_call(int dst, message_t *msg)` - 同步调用(发送+等待回复) ### 6. 系统调用 (cnos_syscall) 通过KAL接口提供系统调用。 **主要系统调用:** - `KAL_SYSCALL_PROCESS` - 进程管理 - `KAL_SYSCALL_IPC` - 进程间通信 - `KAL_SYSCALL_MEMORY` - 内存管理 - `KAL_SYSCALL_INPUT_EVENT` - 输入事件 - `KAL_SYSCALL_GFX_GET_INFO` - 获取图形信息 - `KAL_SYSCALL_GFX_FLUSH` - 刷新帧缓冲 - `KAL_SYSCALL_VFS` - 文件系统操作 ## 驱动程序 ### ATA存储驱动 支持LBA28和LBA48两种模式。 **主要接口:** - `ata_init_primary_master()` - 初始化主盘 - `ata_read28(uint32_t lba, uint8_t count, void *buf)` - LBA28读 - `ata_write28(uint32_t lba, uint8_t count, const void *buf)` - LBA28写 - `ata_read48(uint64_t lba, uint16_t count, void *buf)` - LBA48读 - `ata_write48(uint64_t lba, uint16_t count, const void *buf)` - LBA48写 - `ata_primary_master_sectors()` - 获取磁盘扇区数 ### 图形驱动 支持多种帧缓冲设备: 1. **Intel HD5500** - 集成显卡驱动 2. **QEMU BGA** - QEMU虚拟机BGA帧缓冲 3. **GRUB FB** - Multiboot2提供的帧缓冲 **主要接口:** - `graphics_init(struct vbe_mode_info *vbe)` - 初始化图形 - `graphics_boot_splash()` - 显示启动动画 - `graphics_get_lfb()` - 获取线性帧缓冲地址 - `graphics_get_width()` - 获取屏幕宽度 - `graphics_get_height()` - 获取屏幕高度 - `graphics_get_pitch()` - 获取每行字节数 - `graphics_present()` - 显示帧缓冲内容 ### 其他驱动 - **VGA** - 文本模式输出 - **Serial** - 串口通信(115200bps, 8N1) - **Mouse** - PS/2鼠标,支持3键和滚轮 - **PCI** - PCI设备枚举 - **VirtIO-Net** - 虚拟网络设备 - **VirtIO-GPU** - 虚拟图形设备 - **VirtIO-9P** - 9P文件系统共享 ## VFS文件系统 基于lwext4库实现,支持ext2/3/4文件系统。 ### 块设备抽象层 **cnos_lwext4.c** 提供: 1. **Ramdisk块设备** - 内存模拟块设备 2. **ATA块设备** - 真实硬盘访问 3. **MBR分区表解析** - 传统BIOS分区 4. **GPT分区表解析** - UEFI GUID分区表 ### 设备命名 - `hd0` - ATA Primary Master 整个磁盘 - `hd1~hdN` - 各分区(支持GPT最多128个分区) ## KAL接口 KAL(Kernel Abstraction Layer)是内核与用户态的唯一接口。 ### 系统调用号 | 调用号 | 名称 | 说明 | |--------|------|------| | 53 | KAL_SYSCALL_INPUT_EVENT | 获取输入事件 | | 54 | KAL_SYSCALL_GFX_GET_INFO | 获取图形信息 | | 55 | KAL_SYSCALL_GFX_FLUSH | 刷新显示 | | 56 | KAL_SYSCALL_VFS | 文件系统操作 | ### 输入事件结构 ```c typedef struct { uint32_t type; // 事件类型 uint32_t data1; // 数据1 uint32_t data2; // 数据2 uint32_t data3; // 数据3 } kal_input_event_t; ``` ### 图形信息结构 ```c typedef struct kal_fb_info { void *lfb; // 线性帧缓冲 uint64_t phys; // 物理地址 uint32_t width; // 宽度 uint32_t height; // 高度 uint32_t pitch; // 每行字节数 uint32_t bpp; // 每像素位数 } kal_fb_info_t; ``` ## 构建系统 使用CMake构建系统。 ```bash mkdir build && cd build cmake .. make kernel.elf # 编译内核 make disk_images # 创建磁盘镜像 ``` ### 内核镜像 - 输出: `build/kernel.elf` - 格式: ELF64 - 入口: `kernel_main` - 加载地址: 0x100000 (1MB) ## 内存布局 ``` +------------------+ 0xFFFFFFFFFFFFFFFF (虚拟地址空间顶部) | 内核空间 | 0xFFFF800000000000 - 0xFFFF80FF... |------------------| 0xFFFF800000000000 | 系统保留 | |------------------| | 物理内存映射 | 0xFFFF880000000000 | (直接映射) | (对应0x0开始的物理内存) |------------------| | VMALLOC区域 | (动态分配的页表) |------------------| | 用户空间 | 0x0000000000000000 +------------------+ (用户进程地址空间) ``` ## 中断向量 | 向量号 | 中断源 | 说明 | |--------|--------|------| | 0x00 | 除零错误 | CPU异常 | | 0x06 | 无效操作码 | CPU异常 | | 0x0D | 通用保护 | CPU异常 | | 0x0E | 缺页错误 | CPU异常 | | 0x20 | PIT | 定时器,100Hz | | 0x21 | PS/2键盘 | 键盘中断 | | 0x2C | PS/2鼠标 | 鼠标中断 | | 0x2E | ATA Primary | 硬盘中断 | | 0x80 | 系统调用 | 用户态请求 | | 0xFF | APIC时钟 | 多核时钟 | ## 调度策略 1. **轮转调度** - 所有就绪进程按时间片轮转 2. **时间片** - 定时器每10 ticks触发一次调度 3. **优先级** - 目前所有进程优先级相同 4. **多核支持** - 支持最多8核(MAX_CORES=8) 5. **最大任务数** - 16个任务(MAX_TASKS=16)