姬梦馨linux
原创博客shell
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 函数
存储程序计算机工做模型,计算机系统最最基础性的逻辑结构;spa
函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来讲并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能;操作系统
enter rest
pushl %ebpcode
movl %esp,%ebpblog
leave 进程
movl %ebp,%espip
popl %ebp
函数参数传递机制和局部变量存储
中断,多道程序操做系统的基点,没有中断机制程序只能从头一直运行结束才有可能开始运行其余程序。
2:两个百分号 转移字符
使用实验楼的虚拟机打开shell
而后cd mykernel 您能够看到qemu窗口输出的内容的代码mymain.c和myinterrupt.c
实验代码myinterrupt
及其分析
/*
* 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 //task为空,即发生错误时返回 || my_current_task->next == NULL) { return; } printk(KERN_NOTICE ">>>my_schedule<<<\n"); /* schedule */ next = my_current_task->next;//把当前进程的下一个进程赋给next prev = my_current_task;//当前进程为prev if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */ { /* switch to next process */ /*若是下一个进程的状态是正在执行的话,就运用if语句中的代码表示的方法来切换进程*/ asm volatile( "pushl %%ebp\n\t" /* save ebp 保存当前进程的ebp*/ "movl %%esp,%0\n\t" /* save esp 把当前进程的esp赋给%0(指的是thread.sp),即保存当前进程的esp*/ "movl %2,%%esp\n\t" /* restore esp 把%2(指下一个进程的sp)放入esp中*/ "movl $1f,%1\n\t" /* save eip $1f是接下来的标号“1:”的位置,把eip保存下来*/ "pushl %3\n\t" /*把下一个进程eip压栈*/ "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; }
内核初始化和0号进程启动
实验体会:
实验步骤虽然很简单,但过程是很复杂的,须要本身慢慢的理解,体会。理解代码的过程是很复杂的,须要耐心和认真。
但愿本身之后分析代码的时候可以更加的细心,认真。