网易公开课《Linux内核分析》学习心得-mykernel实验的实践和分析
来源:互联网 发布:php数据库管理系统 编辑:程序博客网 时间:2024/06/10 08:23
网易公开课《Linux内核分析》学习心得-mykernel实验的实践和分析
杨怡泽 原创作品转载请注明出处《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
实验
根据实验要求在实验楼中进行实验,输入命令
cd LinuxKernel/linux-3.9.4qemu -kernel arch/x86/boot/bzImage
得到如下结果:
现在程序中只有一个进程不断运行,但是依然可以分析出进程的启动机制。让我们观察一下mymain.c和myinterrupt.c两个文件中的核心代码。
在mymain.c中:
void __init my_start_kernel(void){ int i = 0; while(1) { i++; if(i%100000 == 0) printk(KERN_NOTICE "my_start_kernel here %d \n",i); }}
这段代码是操作系统的入口,从这里开始操作系统开始执行。
myinterrupt.c中,这段代码是用来处理时钟中断的,时钟中断是由linux内核完成,这段代码的主要功能就是将时钟中断进行处理:
void my_timer_handler(void){ printk(KERN_NOTICE "\n>>>>>>>>>>>>>>>>>my_timer_handler here<<<<<<<<<<<<<<<<<<\n\n");}
现在我们需要在这个的基础上构建一个简单的操作系统。在mykernel文件夹中写入mypcb.h,其主要代码如下:
typedef struct PCB{ int pid; // 表示进程的状态 volatile long state; char stack[KERNEL_STACK_SIZE];// 表示内核的堆栈 /* CPU-specific state of this task */ struct Thread thread; unsigned long task_entry;// 操作系统的程序入口 struct PCB *next;//进程链表 unsigned long priority;}tPCB;
修改mymain.c:
tPCB task[MAX_TASK_NUM]; //task数组tPCB * my_current_task = NULL; //声明当前task指针volatile int my_need_sched = 0; //是否需要标志void my_process(void);unsigned long get_rand(int);void sand_priority(void){ int i; for(i=0;i<MAX_TASK_NUM;i++) task[i].priority=get_rand(PRIORITY_MAX);}void __init my_start_kernel(void){ int pid = 0; //当前进程为0号进程 task[pid].pid = pid; task[pid].state = 0; //状态为正在运行 task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process; task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1]; task[pid].next = &task[pid];//指向自己 /*fork 其他进程 */ for(pid=1;pid<MAX_TASK_NUM;pid++) { memcpy(&task[pid],&task[0],sizeof(tPCB)); task[pid].pid = pid; task[pid].state = -1; task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1]; task[pid].priority=get_rand(PRIORITY_MAX); } task[MAX_TASK_NUM-1].next=&task[0]; printk(KERN_NOTICE "\n\n\n\n\n\n system begin :>>>process 0 running!!!<<<\n\n"); pid = 0; //从零号开始执行 my_current_task = &task[pid]; //开始执行/*嵌入式汇编*/asm volatile( "movl %1,%%esp\n\t" "pushl %1\n\t" "pushl %0\n\t" "ret\n\t" "popl %%ebp\n\t" : : "c" (task[pid].thread.ip),"d" (task[pid].thread.sp)); //汇编代码启动0号进程,内核初始化完成}
这段代码主要是为了启动进程,在asm volatile中初始化完成内核启动0号进程。
修改myinterrupt.c用来启动其他进程和切换进程。如果下一个进程已经执行,则切换进程通过如下代码:
asm volatile( "pushl %%ebp\n\t" /* 保存 ebp */ "movl %%esp,%0\n\t" /* 移动esp到prev->thread.sp处 */ "movl %2,%%esp\n\t" /* 恢复esp */ "movl $1f,%1\n\t" /* 保存 eip */ "pushl %3\n\t" /*调用下一个进程 */ "ret\n\t" /* 恢复 eip */ "1:\t" /* 下一进程开始执行 */ "popl %%ebp\n\t" : "=m" (prev->thread.sp),"=m" (prev->thread.ip) : "m" (next->thread.sp),"m" (next->thread.ip) );
如果下一进程尚未执行,则需要先启动类似进程:
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" "pushl %3\n\t" //保存当前进程的入口 "ret\n\t" : "=m" (prev->thread.sp),"=m" (prev->thread.ip) : "m" (next->thread.sp),"m" (next->thread.ip) );
总结
操作系统的内核通过管理不同进程之间的运行,停止,切换和断点等来实现计算机的运转。当操作系统在运行进程的时候通过实现不同进程之间的切换,来保证每个进程都能顺利进行。当设备满足了读请求时,有一个中断就会通知内核,从而恢复以前的进程继续执行。
0 0
- 网易公开课《Linux内核分析》学习心得-mykernel实验的实践和分析
- 《Linux内核分析》MOOC课-mykernel实验
- 网易公开课《Linux内核分析》学习心得-跟踪分析Linux内核的启动过程
- 网易公开课《Linux内核分析》学习心得-分析Linux内核创建一个新进程的过程
- 网易公开课《Linux内核分析》学习心得-Linux内核如何装载和启动一个可执行程序
- 网易公开课《Linux内核分析》学习心得-Linux内核学习总结
- 网易公开课《Linux内核分析》学习心得-分析system_call中断处理过程
- 网易公开课《Linux内核分析》学习心得-理解进程调度时机跟踪分析进程调度与进程切换的过程
- 《Linux内核分析》-mykernel实验指导(操作系统是如何工作的)
- 网易公开课《Linux内核分析》学习心得-使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
- Linux内核分析,通过mykernel实验分析内核如何工作--第二周
- [网易云课堂]Linux内核分析(二)—— mykernel内核部署及简单时间片轮转程序分析
- Linux内核分析 函数调用堆栈与mykernel实验基础测试
- 基于一个简单内核mykernel的Linux内核时间调度的分析
- 从mykernel来分析linux系统的启动过程
- linux 进程调度程序分析 基于Mykernel
- 从mykernel分析linux任务调度
- mykernel的运行与初步分析
- thinkphp3.2.3开发商城实战(一)
- 栈与队列
- 深入探讨 Java 类加载器
- *LeetCode 90
- 错误记录:Resource ID #0x7f040006 type #0x12 is not valid
- 网易公开课《Linux内核分析》学习心得-mykernel实验的实践和分析
- 一对多 pc上运行android客户端
- [DevExpress]ASP.NET動態設定XtraReport報表參數的方式 5715 ASP.NET 檢舉文章 在ASP.NET中要如何動態設定XtraReport報表參數,或
- TCP
- 文章标题
- iOS/OS X内存管理(一):基本概念与原理
- Android UI学习 - FrameLayou和布局优化
- c++静态断言的实现方式 编译器遇除数为0报错
- Android开发者编码风格