Raspberry Pi OS 项目解析:用户进程与系统调用实现

Raspberry Pi OS 项目解析:用户进程与系统调用实现

raspberry-pi-os Learning operating system development using Linux kernel and Raspberry Pi raspberry-pi-os 项目地址: https://gitcode.com/gh_mirrors/ra/raspberry-pi-os

系统调用基础概念

在操作系统开发中,系统调用(System Call)是用户空间程序与内核交互的标准接口。Raspberry Pi OS 通过实现系统调用机制,为用户程序提供了受限访问内核功能的能力。

系统调用的核心原理是利用处理器提供的异常机制。当用户程序需要执行特权操作时,通过特定指令(如ARM架构的svc)触发同步异常,处理器将控制权转移到内核定义的处理函数。这种设计实现了以下关键特性:

  1. 权限隔离:用户程序运行在EL0(非特权模式),内核运行在EL1(特权模式)
  2. 安全性:内核可以验证所有请求参数后再执行操作
  3. 稳定性:统一的接口保证应用程序的可移植性

Raspberry Pi OS 的系统调用实现

系统调用类型

Raspberry Pi OS 实现了四种基础系统调用:

  1. write:屏幕输出功能

    • 参数:包含待输出文本的缓冲区指针
    • 功能:通过UART设备将文本输出到屏幕
  2. clone:创建新线程

    • 参数:新线程的栈位置
    • 功能:创建与当前进程相同的用户线程
  3. malloc:内存分配

    • 返回值:新分配页面的指针或错误代码
    • 特殊说明:这是一个临时实现,待虚拟内存系统完成后将被替代
  4. exit:进程终止

    • 功能:执行进程清理工作并终止

系统调用处理流程

  1. 用户空间触发

    mov w8, #SYS_WRITE_NUMBER  // 设置系统调用号
    svc #0                     // 触发同步异常
    
  2. 异常处理入口

    • 处理器自动切换到EL1模式
    • 跳转到预设的异常向量表处理程序
  3. 异常分类处理

    mrs x25, esr_el1          // 读取异常原因寄存器
    lsr x24, x25, #ESR_ELx_EC_SHIFT
    cmp x24, #ESR_ELx_EC_SVC64 // 检查是否为系统调用
    
  4. 系统调用分发

    • 验证系统调用号范围
    • 从系统调用表获取处理函数地址
    • 执行对应的处理函数
  5. 返回用户空间

    • 保存返回值
    • 恢复用户上下文
    • 执行eret指令返回EL0

用户模式与特权模式切换

上下文保存与恢复

在模式切换过程中,处理器状态的保存与恢复至关重要:

  1. kernel_entry宏

    • 根据来源异常级别(EL0/EL1)选择正确的栈指针
    • 保存通用寄存器、返回地址和处理器状态
  2. kernel_exit宏

    • 恢复保存的上下文
    • 特别注意sp_el0的恢复
    • 通过eret指令返回

关键寄存器说明

  • ESR_EL1:异常原因寄存器,包含异常类别等信息
  • SPSR_EL1:保存的处理器状态,决定eret返回后的特权级别
  • SP_EL0:EL0级别的栈指针,必须单独保存

用户进程创建机制

从内核线程到用户进程

Raspberry Pi OS采用两步法创建用户进程:

  1. 创建内核线程

    int res = copy_process(PF_KTHREAD, (unsigned long)&kernel_process, 0, 0);
    
  2. 切换到用户模式

    int err = move_to_user_mode((unsigned long)&user_process);
    

move_to_user_mode关键操作

  1. 准备pt_regs结构体:

    • 设置pc指向用户入口函数
    • 配置pstate为PSR_MODE_EL0t
    • 分配用户栈并设置sp
  2. 通过异常返回到用户模式:

    kernel_exit 0  // 0表示从EL0进入的异常
    

用户进程fork实现

clone系统调用实现了用户进程的复制:

  1. 用户空间封装

    int pid = clone(user_stack);
    
  2. 内核处理

    • 调用copy_process创建新任务
    • 复制父进程寄存器状态
    • 设置新的用户栈指针
  3. 子进程启动

    • 从fork返回0
    • 执行指定函数
    • 结束后调用exit

关键数据结构

pt_regs结构

保存异常发生时的处理器状态:

struct pt_regs {
    unsigned long regs[31]; // 通用寄存器
    unsigned long sp;      // 栈指针
    unsigned long pc;      // 程序计数器
    unsigned long pstate;  // 处理器状态
};

任务控制块

扩展了上一版本的任务结构:

  • 新增用户栈指针(stack)
  • 增加标志位区分内核/用户线程
  • 维护抢占计数器(preempt_count)

总结与展望

本篇文章详细分析了Raspberry Pi OS中用户进程和系统调用的实现机制。通过系统调用接口和特权级别隔离,操作系统为用户程序提供了安全受限的执行环境。当前实现还存在以下待改进点:

  1. 缺乏虚拟内存支持(将在第6课实现)
  2. 系统调用种类较少
  3. 错误处理机制简单

这些功能将在后续版本中逐步完善,构建更完整的操作系统功能集。

raspberry-pi-os Learning operating system development using Linux kernel and Raspberry Pi raspberry-pi-os 项目地址: https://gitcode.com/gh_mirrors/ra/raspberry-pi-os

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倪俪珍Phineas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值