第2章 操作系统是如何工作的
一、学习笔记
1. 计算机的三大法宝:存储程序计算、函数调用机制、中断。
2. 堆栈的具体作用有:记录函数调用框架、传递函数参数、保存返回值的地址、提供函数内部局部变量的存储空间等。
3. 堆栈相关的寄存器:
ESP:堆栈指针(stack pointer)
EBP:基址指针(base pointer),在C语言中用作记录当前函数调用基址。
4. 对于X86体系结构来讲,堆栈空间是从高地址向低地址增长的,如图所示:

5. 堆栈操作:
push:栈顶地址减少4个字节(32位),并将操作数放入栈顶存储单元。
pop:栈顶地址增加4个字节(32位),并将栈顶存储单元的内容放入操作数。
6. 其它一些指令:
顺序执行:总是指向地址连续的下一条指令。
跳转/分支:执行这样的指令时,CS:EIP的值会根据程序需要被修改。
call:将当前CS:EIP 的值压入栈顶,CS:EIP指向被调用函数的入口地址。
ret:从栈顶弹出原来保存在这样的CS:EIP的值,放入CS:EIP中。
二、试验记录
1.进程初始化代码
asm volatile(
"movl %1,%%esp\n\t"
"pushl %1\n\t"
"pushl %0\n\t"
"ret\n\t"
"popl %%ebp\n\t"
2.进程0启动,开始执行my_process(void)函数的代码。
if(next->state==0)
{
asm volatile(
"pushl %%ebp\n\t"
"movl %%esp,%0\n\t"
"movl %2,%%esp\n\t"
"movl $1f,%1\n\t"
"pushl %3\n\t"
"ret\n\t"
"1:\t"
"pop1 %%ebp\n\t"
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
);
my_current_task=next;
printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);
}
else
{
next-state=0;
my_current_task=next;
printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);
asm volatile(
"pushl %%ebp\n\t"
"movl %%esp,%0\n\t"
"movl %2,%%esp\n\t"
"movl %2,%%ebp\n\t"
"movl $1f,%1\n\t"
"push %3\n\t"
"ret\n\t"
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
);
}
3.对上述代码的堆栈调用过程进行分析。
为了分析简单,假设系统只有两个进程,分别是进程0和进程1.进程0由内核启动时初始化执行,然后需要进程调度,开始执行进程1。下面从进程1被调度开始分析堆栈变化,因为进程1从来没有被执行过,是第一次被调度执行,此时执行else中的代码。

到这里开始执行进程1,如果进程1执行的过程中发生了进程调度,进程0重新被调度执行了,应该执行前述if中的代码,具体的堆栈变化与上图所示过程相似。
总结
本章内容最重要的是进程的切换,进程在执行过程中,当时间片用完需要进程切换时,需要先保存当前的进程执行的上下文环境,下次进程被调度时,需要恢复进程的上下文环境。这样实现多道程序的并发执行。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】