操作系统是如何工作的--知识总结及实验报告

操作系统是如何工作的

攥写人:杨光  学号:20135233

( *原创作品转载请注明出处*)

( 学习课程:《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 )

知识总结:

***计算机工作的三个法宝

存储程序计算机、中断机制、堆栈

***堆栈的作用

  1. 函数调用框架
  2. 传递参数
  3. 保存返回地址
  4. 提供局部变量空间

***堆栈用到的寄存器

  1. esp,指向栈顶
  2. ebp,指向栈底,在C语言中用作记录当前函数调用基址。

***EIP寄存器

cs:eip:总是指向下一条的指令地址

顺序执行:总是指向地址连续的下一条指令

跳转/分支:cs : eip的值会根据程序需要被修改

***C代码中嵌入汇编代码的写法

与汇编代码不一样的地方有:

寄存器前双%                   例子:movl $3,%%ebp;

%加数字,代表代码末的输出或输入   例子:addl %1,%%eax;    

                 :"d"(val1)     /*d代表edx寄存器*/

                 :"c"(val2)      /*c代表ecx寄存器*/

                即为把val2赋给eax

********************************分割线就是我********************************

实验要求:

运行并分析一个精简的操作系统内核,理解操作系统是如何工作的

 使用实验楼的虚拟机打开shell

  1. cd LinuxKernel/linux-3.9.4
  2. qemu -kernel arch/x86/boot/bzImage

然后cd mykernel 您可以看到qemu窗口输出的内容的代码mymain.c和myinterrupt.c

完成一个简单的时间片轮转多道程序内核代码,代码见视频中或从mykernel找。

实验过程:

1.mykernel

 

 

 

以上是实验楼中的实验运行结果和代码查看

********************************分割线就是我********************************

2.一个简单的操作系统内核源代码

 

1.mypcb.h    //头文件    定义自己的进程信息控制块

************************************************************** 

10 #define MAX_TASK_NUM 4 
11 #define KERNEL_STACK_SIZE   1024*8 
12 
 
13 /* CPU-specific state of this task */ 
14 struct Thread { 
15 unsigned long        ip; 
16 unsigned long        sp; 
17 }; 
18 
 
19 typedef struct PCB{ 
20 int pid; 
21 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ 
22 char stack[KERNEL_STACK_SIZE]; 
23 /* CPU-specific state of this task */ 
24 struct Thread thread; 
25 unsigned long    task_entry; 
26 struct PCB *next; 
27 }tPCB; 
28 
 
29 void my_schedule(void); 

 ************************************************************** 

2.mymain.c                              //主函数

 ************************************************************** 

16 #include "mypcb.h" 
17 
 
18 tPCB task[MAX_TASK_NUM]; 
19 tPCB * my_current_task = NULL; 
20 volatile int my_need_sched = 0; 
21 
 
22 void my_process(void); 
23 
24 
 
25 void __init my_start_kernel(void) 
26 { 
27 int pid = 0; 
28 int i; 
29 /* Initialize process 0*/ 
30 task[pid].pid = pid; 
31 task[pid].state = 0;
32 task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process; 
33 task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1]; 
34 task[pid].next = &task[pid]; 

35 /*fork more process */ 
36 for(i=1;i<MAX_TASK_NUM;i++) 
37 { 
38 memcpy(&task[i],&task[0],sizeof(tPCB)); 
39 task[i].pid = i; 
40 task[i].state = -1; 
41 task[i].thread.sp = (unsigned long)&task[i].stack[KERNEL_STACK_SIZE-1]; 
42 task[i].next = task[i-1].next; 
43 task[i-1].next = &task[i]; 
44 } 

45 /* start process 0 by task[0] */ 
46 pid = 0;
47 my_current_task = &task[pid]; 
48  asm volatile( 
49  "movl %1,%%esp\n\t"     /* set task[pid].thread.sp to esp */ 
50  "pushl %1\n\t"  /* push ebp */ 
51  "pushl %0\n\t"  /* push task[pid].thread.ip */ 
52  "ret\n\t"   /* pop task[pid].thread.ip to eip */ 
53  "popl %%ebp\n\t" //弹出来ebp,内核初始化工作完成
54  :  
55  : "c" (task[pid].thread.ip),"d" (task[pid].thread.sp)   /* input c or d mean %ecx/%edx*/ 
56  ); 
57 }

58 void my_process(void)
59 { 
60 int i = 0; 
61 while(1) 
62 { 
63 i++; 
64 if(i%10000000 == 0) 
65 { 
66 printk(KERN_NOTICE "this is process %d -\n",my_current_task->pid); 
67 if(my_need_sched == 1) //执行10 000 000次才判断一次是否需要调度
68 { 
69 my_need_sched = 0; 
70  my_schedule(); 
71  } 
72  printk(KERN_NOTICE "this is process %d +\n",my_current_task->pid); 
73 }  
74 } 
75 } 

 ************************************************************** 

3.myinterrupt.c         //中断调度机制

 ************************************************************** 

15 #include "mypcb.h" 
16 
 
17 extern tPCB task[MAX_TASK_NUM]; 
18 extern tPCB * my_current_task; 
19 extern volatile int my_need_sched; 
20 volatile int time_count = 0; 
21 
 
22 /* 
23  * Called by timer interrupt. 
24  * it runs in the name of current running process, 
25  * so it use kernel stack of current running process 
26  */ 
27 void my_timer_handler(void) 
28 { 
29 #if 1 
30 if(time_count%1000 == 0 && my_need_sched != 1) 
31 { 
32 printk(KERN_NOTICE ">>>my_timer_handler here<<<\n"); 
33 my_need_sched = 1; 
34 }  
35 time_count ++ ;   
36 #endif 
37 return;       
38 } 
39 
 
40 void my_schedule(void) 
41 { 
42 tPCB * next; 
43 tPCB * prev; 
44 
 
45 if(my_current_task == NULL  
46 || my_current_task->next == NULL) 
47 { 
48  return; 
49 } 
50 printk(KERN_NOTICE ">>>my_schedule<<<\n"); 

51 /* schedule */ 
52 next = my_current_task->next; 
53 prev = my_current_task; 

54 if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */ //在两个正在执行的进程之间做上下文切换
55 { 
56  /* switch to next process */ 
57  asm volatile(    
58  "pushl %%ebp\n\t"   /* save ebp */ 
59  "movl %%esp,%0\n\t"     /* save esp */ 
60  "movl %2,%%esp\n\t" /* restore  esp */ 
61  "movl $1f,%1\n\t"   /* save eip */ //$1f就是指标号1:的代码在内存中存储的地址  
62  "pushl %3\n\t"  
63  "ret\n\t"   /* restore  eip */ 
64  "1:\t"  /* next process start here */ 
65  "popl %%ebp\n\t" 
66  : "=m" (prev->thread.sp),"=m" (prev->thread.ip) 
67  : "m" (next->thread.sp),"m" (next->thread.ip) 
68  );  
69  my_current_task = next;  
70  printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid     
71 } 

72 else 
73 { 
74 next->state = 0; 
75 my_current_task = next; 
76 printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid); 
77  /* switch to new process */ 
78  asm volatile(    
79  "pushl %%ebp\n\t"   /* save ebp */ 
80  "movl %%esp,%0\n\t"     /* save esp */ 
81  "movl %2,%%esp\n\t" /* restore  esp */ 
82  "movl %2,%%ebp\n\t" /* restore  ebp */ 
83  "movl $1f,%1\n\t"   /* save eip */   
84  "pushl %3\n\t"  
85  "ret\n\t"   /* restore  eip */ 
86  : "=m" (prev->thread.sp),"=m" (prev->thread.ip) 
87  : "m" (next->thread.sp),"m" (next->thread.ip) 
88  );   
89 }
90 return;   
91 }

 ************************************************************** 

总结:

    操作系统在发生中断时,保留上下文(堆栈),即保存现场,然后进行进程切换,以此完成工作。

posted @ 2016-03-06 15:10  Mccartney  阅读(408)  评论(0编辑  收藏  举报