作者:20135336 王维臻
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、实验过程
cd LinuxKernel/linux-3.9.4 qemu -kernel arch/x86/boot/bzImage
然后cd mykernel 您可以看到qemu窗口输出的内容的代码mymain.c和myinterrupt.c
1.mymain.c代码
/* * linux/mykernel/myinterrupt.c * * Kernel internal my_timer_handler * * Copyright (C) 2013 Mengning * */ #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include <linux/tty.h> #include <linux/vmalloc.h> #include "mypcb.h" extern tPCB task[MAX_TASK_NUM]; extern tPCB * my_current_task; extern volatile int my_need_sched; volatile int time_count = 0; /* * Called by timer interrupt. * it runs in the name of current running process, * so it use kernel stack of current running process */ void my_timer_handler(void) { #if 1 if(time_count%1000 == 0 && my_need_sched != 1) { printk(KERN_NOTICE ">>>my_timer_handler here<<<\n"); my_need_sched = 1; } time_count ++ ; #endif return; } 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; }
每循环十万次打印一个printk(KERN_NOTICE "my_start_kernel here %d \n",i);
2.myinterrupt.c代码
/* * linux/mykernel/myinterrupt.c * * Kernel internal my_timer_handler * * Copyright (C) 2013 Mengning * */ #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include <linux/tty.h> #include <linux/vmalloc.h> #include "mypcb.h" extern tPCB task[MAX_TASK_NUM]; extern tPCB * my_current_task; extern volatile int my_need_sched; volatile int time_count = 0; /* * Called by timer interrupt. * it runs in the name of current running process, * so it use kernel stack of current running process */ void my_timer_handler(void) { #if 1 if(time_count%1000 == 0 && my_need_sched != 1) { printk(KERN_NOTICE ">>>my_timer_handler here<<<\n"); my_need_sched = 1; } time_count ++ ; #endif return; } 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; }
每次时钟中断都调用一次printk(),printk(KERN_NOTICE "\n>>>>>>>>>>>>>>>>>my_timer_handler here<<<<<<<<<<<<<<<<<<\n\n");
二、学习内容
(一)计算机是如何工作的?
1.存储程序计算机工作模型,计算机系统最最基础性的逻辑结构;
2.函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能;
enter :pushl %ebp
movl %esp,%ebp
leave :movl %ebp,%esp
- popl %ebp
- 函数参数传递机制和局部变量存储
- 3.中断,多道程序操作系统的基点,没有中断机制程序只能从头一直运行结束才有可能开始运行其他程序。
- (二)函数调用堆栈
- 堆栈
- 1.堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间。
- 2.堆栈存在的目的:函数调用框架;传递参数;保存返回地址;提供局部变量空间;
- 3.了解堆栈存在的目的和编译器对堆栈使用的规则是理解操 作系统一些关键性代码的基础。
- 堆栈寄存器和堆栈操作
- 1.堆栈相关的寄存器:esp,堆栈指针(stack pointer):ebp,基址指针(base pointer)
- 2.堆栈操作:push 栈顶地址减少4个字节(32位) pop 栈顶地址增加4个字节
- 3.ebp在C语言中用作记录当前函数调用基址
- (三)借助Linux内核部分源代码模拟存储程序计算机工作模型及时钟中断
- (四)在mykernel基础上构造一个简单的操作系统内核
- 三、学习心得
- 在这次学习中我通过内核源代码了解,从环境搭建起来,mystartkernerl开始初始化至完成,启动0号进程,利用时间片,每个进程每隔1000万次,判断是否需要调度,调度使用myshedule()进行调度.设置时间片的大小,时间片用完时,设置一下调度标识。调度分两种情况,一种是下一个进程正在进行的,另一种是从未调度过的,进程从未执行过,执行起来特殊点,将状态转成运行时状态,作为当前执行的进程。
时间: 2024-10-18 14:07:37