本周首先我结合mooc网的视频资料,了解了计算机的三大法宝,分别是存储程序计算机,函数调用堆栈和中断机制。
在计算机的三大法宝中,存储程序计算机是根本,函数调用堆栈是高级语言运行的基础,而中断机制成就了多道程序运行的先河。
push %ebp; movl %esp,%ebp; do something; movel %ebp,%esp; popl %ebp; ret
- 前两行指令建立了被调用者函数的堆栈框架
- 中间一行指令为被调用者执行的操作
- 最后三行指令为拆除被调用者函数的堆栈框架,并返回。
#实验二搭建实验模拟时钟中断。
>cd LinuxKernel/linux-3.9.4 >qemu -kernel arch/x86/boot/bzImage >vi mymain.c
>vi myinterrupt.c
这段代码定义了一个名为Thread的结构体,用于保存ip和sp。然后定义了进程描述符PCB结构体,其中包括进程号pid,进程状态state、进程的堆栈、进程的Thread(ip和sp)、程序入口task_entry、下一个进程的进程描述符*next、优先权priority。最后还生命了一个调度器my_schedule(void)。
下面来看mymain.c,
void __init my_start_kernel(void) { int pid = 0; /* Initialize process 0/ task[pid].pid = pid; task[pid].state = 0;/ -1 unrunnable, 0 runnable, 0 stopped /// set task 0 execute entry address to my_process 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 more process / for(pid=1;pid该函数是初始化系统内核的,首先创建0号进程,初始化了一个只有一个PCB的循环链表。然后通过循环扩充链表,memcpy()函数将0号进程的所有数据拷贝到多个PCB中并对多个PCB数据进行修改。最后初始化堆栈ebp、esp、eip。>>process 0 running!!!<<<\n\n");/ start process 0 by task[0] / pid = 0; my_current_task = &task[pid]; asm volatile( "movl %1,%%esp\n\t" / set task[pid].thread.sp to esp / "pushl %1\n\t" / push ebp / "pushl %0\n\t" / push task[pid].thread.ip / "ret\n\t" / pop task[pid].thread.ip to eip / "popl %%ebp\n\t" : : "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) / input c or d mean %ecx/%edx*/ );
void my_process(void) { int i = 0; while(1) { i++; if(i%10000000 == 0) { if(my_need_sched == 1) { my_need_sched = 0; sand_priority(); my_schedule();
} }}
}
该函数定义了时间片。 void my_timer_handler(void) { //if 1 // make sure need schedule after system circle 2000 times. if(time_count%2000 == 0 && my_need_sched != 1) { my_need_sched = 1; //time_count=0; } time_count ++ ; //endif return; }当发生中断时,把my_need_sched的值改成1.这时my_process中if部分开始,把my_need_sched复位为0,并调用my-schedul。 <
if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped / { //save current scene / 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;//switch to the next task printk(KERN_NOTICE " switch from %d process to %d process\n >>>process %d running!!!<<<\n\n",prev->pid,next->pid,next->pid);
} else { next->state = 0; my_current_task = next; printk(KERN_NOTICE " switch from %d process to %d process\n >>>process %d running!!!<<<\n\n\n",prev->pid,next->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) );}
跳转到下一个进程。 然后学习了linux内核与分析的课本内容
在第三章知道了struct thraead_info在文件<asm/thread_info.h>中的具体定义。
struct thread_info { struct task_struct task; / main task structure / __u32 flags; / low level flags / __u32 status; /* thread synchronous flags/ __u32 cpu; / current CPU / mm_segment_t addr_limit; unsigned int sig_on_uaccess_error:1; unsigned int uaccess_err:1; / uaccess failed / };state域中的五种进程状态,运行,可中断,不可中断,被其他进程追踪,停止状态。以及创建进程的fork和clone,装入地址空间的exec,收集后代信息的wait,消亡进程的exit。 在第五章主要学习了系统调用的一些基本内容,包括内核的通信,应用程序通过在用户空间实现的应用编程接口来调用系统命令。理解了Linux如何实现系统调用和执行系统调用。 对本次学习的进程结合本科期间操作系统里面简述的进程对系统的进程调度和运行有了一个全新的认识!