这回由启动时初始化的顺序分析涉及几个bootstrap函数的文件。
/kern/arch/mips/mips/ram.c
ram_bootstrap()
21 获取当前内存大小
23-32 内存最大为508MB,因为由于mips体系的原因,超出这个大小,内存将不连续了。
34 lastpaddr为内存最后一个字节的地址
36-40 firstpaddr为firstfree-MIPS_KSEG0,firstfree为当前内核堆栈的栈顶
42-44 打印cpu型号和内存可用值
paddr_t ram_stealmem(unsigned long npages)
66-67 size等于请求页数的字节数
69-71 如果大于可分配空间,就返回0(物理上不非法,但逻辑上非法的地址)
73-76 返回当前firstpaddr的地址,并将firstpaddr后移size个字节
ram_getsize(u_int32_t *lo, u_int32_t *hi)
87-89 将可用空间的起止地址传回,*lo为起始地址,*hi为终止地址。并将firstpaddr和lastpaddr置0,相当于交出空白空间。
/kern/thread/scheduler.c
15-20 声明runqueue来存储运行时task,struct queue定义在了/kern/lib/queue.c (10-15)中:
int size;
int nextwrite; // next element to write to (was head)
int nextread; // next element to read from (was tail)
void **data;
};
scheduler_boostrap()
28-31 调用q_create(32),生成一个长度为32的队列作为runqueue。如果失败就panic
int scheduler_preallocate(int nthreads)
45 调用q_preallocate()来为nthreads个线程预分配空间。
void scheduler_killall(void)
58-61 这个函数用于在panic shutdown的时候,将所有runqueue中的thread清除掉。
void scheduler_shutdown()
74 调用scheduler_killall(),杀掉所有的threads
77-78 清除runqueue
struct thread * scheduler(void)
93-95 这个函数是真正的调度器。如果runqueue是空的,那么调用cpu_idle()休息一会儿,过会儿循环回来判断runqueue。
97-102 去掉print_run_queue()前的注释后,可以打印runqueue
104 将runqueue的第一个task取出,并返回。这实际上是roundrobin的轮转调度算法,最简单的一种。
int make_runnable(struct thread *t)
117 通过调用q_addtail(runqueue, t),将thread t添加到runqueue的尾部。
void print_run_queue(void)
127 关中断
129-130 取得runqueue其实位置
132-137 循环到runqueue结束,打印每一个runqueue线程中的名称和地址。
139 开中断
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构