StarryNext源代码阅读

Starry Next 源代码阅读

run_user_app:

  • 新建用户地址空间
  • 把内核地址空间复制到应用地址空间高地址区域 (ArceOS 特性)
  • 设置当前目录
  • set_current_dir 设置当前目录 全局变量 CURRENT_DIR
  • load_user_app
    • 借助创建的用户地址空间和传入的参数
    • 读取 ELF 数据, 加载 ld.so/libc.so
    • 在用户地址空间映射可执行文件的各个逻辑段
    • 通过预先布局的汇编常量地址和大小映射用户栈到用户地址空间, 初始化用户栈内容
    • 在用户地址空间映射堆区.
    • 返回起始运行地址和用户栈栈指针
  • 准备用户地址空间上下文(管理 Trap 上下文, 例如通用寄存器状态, CSRs)
  • 新建用户任务, 传一个切进用户态的闭包进去
  • 设置根页表位置, RISCV SV39 下就是 satp
  • 准备进程和线程相关数据, FD_TABLE CURRENT_DIR tid
  • 把主线程添加到全局线程表中, 把任务添加到待执行队列等待调度

main:

  • 宏内核扩展, 相当于一个”应用程序的 main”
  • 启动 init 进程, 运行 testcases

handle_page_fault:

  • 当前任务的地址空间执行 handle_page_fault, 失败则 SIGSEGV 信号退出

handle_syscall:

  • 依赖 syscalls crate 的 Sysno, 根据 id 匹配一下具体的 syscall 类型, 分发到对应处理函数, 返回执行结果

map_elf:

  • 解析参数传来的 elf 数据, 对每个段进行映射
  • todo!("有关 ELFParser::new 中有关 Interpreter的问题")?

TaskExt:

  • ArceOS 中的任务控制块扩展. 对于宏内核扩展就是需要线程相关的 tid
  • axtask::def_task_ext! 宏注册任务控制块扩展
  • thread 中的数据除了 tid 还有一个 Data 字段.
  • ThreadData clear_chlld_tid?

ProcessData:

  • 可执行文件的路径
  • 用户地址空间
  • 堆内存的起始和终止地址
  • ProcessData 中为什么没有线程相关/任务相关数据?
  • AxNamespace?

#[percpu::def_percpu]?

access_user_memory ?

time 相关 ?


check_region: 检查一段地址是否对齐存在且可访问

check_null_terminated: 返回 [start, 第一个 T::default 的地址]

PtrWrapper Trait: 指针的基本操作, 以及各种 get_as

单独系统调用: uname, sys_times

sys_mmap sys_waitpid 和 ArceOS 一致

sys_mprotect 是干嘛的?

sys_arch_prctl: 用于设置 (架构相关的) 用户态线程局部存储寄存器, 例如 FS(TLS 结构体) GS (per_CPU 数据, 如进程控制块)

cleaR_child_tid:

用户态的 tidptr: *mut i32 变量, 初始值指向线程栈上 gettid() 的返回值, 置 0 时表示线程退出

内核栈上 clear_child_tidtidptr 指向相同的内存地址, 退出时将其指向的位置置 0 表示退出

sys_set_tid_address:

do_exit: 被 sys_exit/sys_exit_group 依赖, exit_group 为 T/F 的差别

  • 置 0 clear_child_tid
  • 退出主线程

信号量机制


直接开写 lab 吧, 整体了解没什么硬伤, 任务驱动学习好了