《Linux内核分析》 操作系统是如何工作的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Linux内核分析》 操作系统是如何工作的相关的知识,希望对你有一定的参考价值。

范闻泽   原创作品转载请注明出处   《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

 

技术分享

根据实验要求,在实验楼中的运行。

技术分享

时间片轮转法

 

 技术分享

 

(输入vi main.c查看mykernel的源代码)

 

 技术分享

 

mymain.c中最核心的代码

 

 

技术分享

(myinterrupt.c的代码,每次时钟中断调用一次printk)

 

 

2.操作系统内核源代码【分析见注释】

1.mypcb.h//头文件,在其他的.c文件中引用;主要是数据结构的定义

1   /* 
2  *  linux/mykernel/mypcb.h 
3  * 
4  *  Kernel internal PCB types 
5  * 
6  *  Copyright (C) 2013  Mengning 
7  * 
8  */ 
9 

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; //定义进程id
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 内核初始化和0号进程启动

1   /* 
2  *  linux/mykernel/mymain.c 
3  * 
4  *  Kernel internal my_start_kernel 
5  * 
6  *  Copyright (C) 2013  Mengning 
7  * 
8  */ 
9  #include <linux/types.h> 
10 #include <linux/string.h> 
11 #include <linux/ctype.h> 
12 #include <linux/tty.h> 
13 #include <linux/vmalloc.h> 
14      
15 

16 #include "mypcb.h" 
17 

18 tPCB task[MAX_TASK_NUM]; //声明一个pcb数组
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*/ //初始化0号进程数据结构
30 task[pid].pid = pid; 
31 task[pid].state = 0;/* -1 不可运行, 0 可运行, >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]; //堆栈的栈顶位置,在mypcb.h中也有定义
34 task[pid].next = &task[pid]; //next指向自己

35 /*fork more process */ 
36 for(i=1;i<MAX_TASK_NUM;i++) 
37 { 
38 memcpy(&task[i],&task[0],sizeof(tPCB)); //复制0号进程的状态
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] */ //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 */ //确定esp的位置
50  "pushl %1\n\t"  /* push ebp */ //ebp等于esp
51  "pushl %0\n\t"  /* push task[pid].thread.ip */ //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) 
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 } 

3myinterrupt.c 调度机制

1  /* 
2  *  linux/mykernel/myinterrupt.c 
3  * 
4  *  Kernel internal my_timer_handler 
5  * 
6  *  Copyright (C) 2013  Mengning 
7  * 
8  */ 
9 #include <linux/types.h> 
10 #include <linux/string.h> 
11 #include <linux/ctype.h> 
12 #include <linux/tty.h> 
13 #include <linux/vmalloc.h> 
14 
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 */   
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 } 


3.总结

1.存储程序计算机,中断机制和堆栈使计算机变得更加简单方便。

2.中断和上下文进程切换是操作系统的必备操作。

以上是关于《Linux内核分析》 操作系统是如何工作的的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核分析:完成一个简单的时间片轮转多道程序内核代码

《Linux内核分析》 操作系统是如何工作的

《Linux内核分析》 第二节 操作系统是如何工作的

完成一个简单的时间片轮转多道程序内核代码

第二周:一个简单的时间片轮转多道程序内核代码及分析

操作系统是如何进行工作的