万子惠 + 原创作品转载请注明出处 + 《Linux内核分析》

实验部分

使用实验楼的虚拟机打开shell
然后cd mykernel 您可以看到qemu窗口输出的内容的代码mymain.c和myinterrupt.c

my_time_handler(调用printk //实际时会做一些中断处理)

my_start_kernel(进行硬件初始化的工作)

总结部分

来自老师的计算机是如何工作的总结——三个法宝

  • 存储程序计算机工作模型,计算机系统最最基础性的逻辑结构;

  • 函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能。

    enter =>pushl %ebp
    ,movl %esp,%ebp

    leave =>movl %ebp,%esp
    ,popl %ebp

  • 函数参数传递机制和局部变量存储

  • 中断,多道程序操作系统的基点,没有中断机制程序只能从头一直运行结束才有可能开始运行其他程序


Part1 进程变化学习总结

进程专属堆栈
进程调度=>切换堆栈

函数堆栈框架的形成

call xx:cs:eip原来的值被保存,cs:eip指向下条指令(xx入口值)

进入xx:pushl %ebp
		movl %esp,%ebp	
		//函数常规的其他操作

退出xx: movl %ebp,%esp (清空操作)
		popl %ebp (ebp返回原基地址)
		ret (cs:eip出栈)

*在main函数中,会先预留空间,为其他函数调用产生的局部变量进行存储。

有压栈必有出栈,有生必有死

堆栈变化总结

main开始执行=>调用p1=>压栈参数
				   =>压栈eip
				   =>ret

Part2 操作系统是如何工作的学习总结

操作系统的两把剑:

         中断上下文           +进程上下文切换
    	|        |
   保存现场       恢复现场

中断:中断信号发生时,cpu和内核代码共同实现保存现场和恢复现场。

将当前esp,ebp,eip压入进程中,然后将eip指向中断处理程序入口。
(实验中可以看到系统只有一个进程执行,每隔一段时间,发生一个时间中断)

进程切换

两种情况:

  • 下一个进程 正在执行(next_state==0):
  • 全新进程型:

实验代码(可以看出略不同):

void my_schedule(void)
{
tPCB * next;
tPCB * prev;

if(my_current_task == NULL 
    || my_current_task->next == NULL)
{
	return;
}
printk(KERN_NOTICE ">>>my_schedule<<<\n");
/* schedule */
next = my_current_task->next;
prev = my_current_task;
if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */
{
	/* switch to next process */
	asm volatile(	
    	"pushl %%ebp\n\t" 	    /* save ebp */
    	"movl %%esp,%0\n\t" 	/* save esp */
    	"movl %2,%%esp\n\t"     /* restore  esp */
    	"movl $1f,%1\n\t"       /* save eip */	
    	"pushl %3\n\t" 
    	"ret\n\t" 	            /* restore  eip */
    	"1:\t"                  /* next process start here */
    	"popl %%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);
	/* switch to new process */
	asm volatile(	
    	"pushl %%ebp\n\t" 	    /* save ebp */
    	"movl %%esp,%0\n\t" 	/* save esp */
    	"movl %2,%%esp\n\t"     /* restore  esp */
    	"movl %2,%%ebp\n\t"     /* restore  ebp */
    	"movl $1f,%1\n\t"       /* save eip */	
    	"pushl %3\n\t" 
    	"ret\n\t" 	            /* restore  eip */
    	: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
    	: "m" (next->thread.sp),"m" (next->thread.ip)
	);          
}   
return;	
}

内嵌写法

asm("statments":out_regs(输出部分):input_regs(输入部分):input_regs:clobbered_regs(破坏部分));

这里附一张老师的常用限定符:

Part3 对“操作系统是如何工作的”理解

对我来说,操作系统在启动之后就开始持续运行,每隔一段时间就由中断机制来打算运行的状态,来进行调整,由此来进行多道程序的实现,和异常的处理,最后使得人机的更好地交互,操作系统也获得更强大的功能。