zoukankan      html  css  js  c++  java
  • 2019-2020-1 20199326《Linux内核原理与分析》第三周作业

    第三周学习内容

    庖丁解牛Linux内核分析第二章:操作系统是如何工作的
    Linux内核分析实验二

    学到的一些知识

    • 计算机的三大法宝:存储程序计算机,函数调用堆栈,中断

    • 堆栈是C语言程序运行时必须使用的记录函数调用路径和参数存储的空间,堆栈具体的作用有:记录函数调用框架,传递函数参数,保存返回值的地址,提供函数内部局部变量的存储空间等

    • 与堆栈相关的寄存器:ESP,EBP

    • 堆栈操作:push,pop

    • CS:EIP总是指向下一条的指令地址

      • 顺序执行:总是指向地址连续的下一条指令
      • 跳转/分支:执行这样的指令时,CS:EIP的值会根据程序需要被修改
      • call:将当前的CS:EIP的值压入栈顶,CS:EIP指向被调用函数的入口地址
      • ret:从栈顶弹出原来保存在这里的CS:EIP的值,放入CS:EIP中
    • 如果两个机器的处理器指令集不同,汇编出来的汇编代码也会有所不同

    实验内容

    1.虚拟一个x86的CPU硬件平台

    在实验楼的环境中打开shell,输入两行代码即可启动内核:

    $ cd ~/LinuxKernel/linux-3.9.4
    $ qemu -kernel arch/x86/boot/bzImage
    

    内核启动后如图:

    进入mykernel查看mymain.c和myinterrupt.c,如图所示:

    2.在mykernel基础上构造一个简单地操作系统内核

    增加一个mypcb.h的头文件

    #define MAX_TASK_NUM 10 // 最大进程数
    #define KERNEL_STACK_SIZE 1024*8
    #define PRIORITY_MAX 30 //从0到30的优先级
    
    /* CPU-specific state of this task */
    struct Thread {
    unsigned long	ip;//point to cpu run address
    unsigned long	sp;//point to the thread stack's top address
    //todo add other attrubte of system thread
    };
    //PCB Struct
    typedef struct PCB{
    int pid; // pcb id 
    volatile long state;	/* -1 不运行, 0 运行, >0 停止 */
    char stack[KERNEL_STACK_SIZE];// each pcb stack size is 1024*8
    /* CPU-specific state of this task */
    struct Thread thread;
    unsigned long	task_entry;//the task execute entry memory address
    struct PCB *next;//pcb is a circular linked list
    unsigned long priority;// task priority ////////
    //todo add other attrubte of process control block
    }tPCB;
    
    //void my_schedule(int pid);
    void my_schedule(void);
    

    修改mymain.c

    #ifdef CONFIG_X86_LOCAL_APIC
    #include <asm/smp.h>
    #endif
    #include "mypcb.h"
    
    tPCB task[MAX_TASK_NUM];
    tPCB * my_current_task = NULL;
    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;
    /* 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<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);//each time all tasks get a random priority
    }
    	task[MAX_TASK_NUM-1].next=&task[0];
    printk(KERN_NOTICE "
    
    
    
    
    
    system begin :>>>process 0 running!!!<<<
    
    ");
    /* start process 0 by task[0] */
    pid = 0;
    my_current_task = &task[pid];
    asm volatile(
     "movl %1,%%esp
    	" /* set task[pid].thread.sp to esp */
     "pushl %1
    	" /* push ebp */
     "pushl %0
    	" /* push task[pid].thread.ip */
     "ret
    	" /* pop task[pid].thread.ip to eip */
     "popl %%ebp
    	"
     :
     : "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();  
    		
    	   }
    }
    }
    }//end of my_process
    
    //produce a random priority to a task
    unsigned long get_rand(max)
    {
    	unsigned long a;
    	unsigned long umax;
    	umax=(unsigned long)max;
     	get_random_bytes(&a, sizeof(unsigned long ));
    	a=(a+umax)%umax;
    	return a;
    }
    

    修改myinterrupt.c

    #include "mypcb.h"
    
    #define CREATE_TRACE_POINTS
    #include <trace/events/timer.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
    // 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;
    }
    
    void all_task_print(void);
    
    tPCB * get_next(void)
    {
    	int pid,i;
    	tPCB * point=NULL;
    	tPCB * hig_pri=NULL;//points to the the hightest task
    	all_task_print();
    	hig_pri=my_current_task;
    	for(i=0;i<MAX_TASK_NUM;i++)
    		if(task[i].priority<hig_pri->priority)	
    			hig_pri=&task[i];
    	printk("higst process is:%d priority is:%d
    ",hig_pri->pid,hig_pri->priority);
    	return hig_pri;
    
    }//end of priority_schedule
    
    void my_schedule(void)
    {
    tPCB * next;
    tPCB * prev;
    // if there no task running or only a task ,it shouldn't need schedule
    if(my_current_task == NULL
    || my_current_task->next == NULL)
    {
    	printk(KERN_NOTICE "time out!!!,but no more than 2 task,need not schedule
    ");
     return;
    }
    /* schedule */
    
    next = get_next();
    prev = my_current_task;
    printk(KERN_NOTICE "the next task is %d priority is %u
    ",next->pid,next->priority);
    if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */
    {//save current scene
     /* switch to next process */
     asm volatile(	
     "pushl %%ebp
    	" /* save ebp */
     "movl %%esp,%0
    	" /* save esp */
     "movl %2,%%esp
    	" /* restore esp */
     "movl $1f,%1
    	" /* save eip */	
     "pushl %3
    	"
     "ret
    	" /* restore eip */
     "1:	" /* next process start here */
     "popl %%ebp
    	"
     : "=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
    >>>process %d running!!!<<<
    
    ",prev->pid,next->pid,next->pid);
    
      }
    else
    {
    next->state = 0;
    my_current_task = next;
    printk(KERN_NOTICE "switch from %d process to %d process
    >>>process %d running!!!<<<
    
    
    ",prev->pid,next->pid,next->pid);
    
     /* switch to new process */
     asm volatile(	
     "pushl %%ebp
    	" /* save ebp */
     "movl %%esp,%0
    	" /* save esp */
     "movl %2,%%esp
    	" /* restore esp */
     "movl %2,%%ebp
    	" /* restore ebp */
     "movl $1f,%1
    	" /* save eip */	
     "pushl %3
    	"
     "ret
    	" /* restore eip */
     : "=m" (prev->thread.sp),"=m" (prev->thread.ip)
     : "m" (next->thread.sp),"m" (next->thread.ip)
     );
    }
    return;	
    }//end of my_schedule
    
    void all_task_print(void)
    {
    	int i,cnum=62;//
    	printk(KERN_NOTICE "
    current task is:%d   all task in OS are:
    ",my_current_task->pid);
    
    	printk("");
    	for(i=0;i<cnum;i++)
    		printk("-");
    	printk("
    |  process:");
    	for(i=0;i< MAX_TASK_NUM;i++)
    		printk("| %2d ",i);
    	printk("|
    | priority:");
    	for(i=0;i<MAX_TASK_NUM;i++)
    		printk("| %2d ",task[i].priority);
    
    	printk("|
    ");
    	for(i=0;i<cnum;i++)
    		printk("-");
    	printk("
    ");
    }
    

    重新编译,输入以下代码:

    $ cd ~/LinuxKernel/linux-3.9.4
    $ make
    $ qemu -kernel arch/x86/boot/bzImage
    

    结果如图所示

  • 相关阅读:
    lr 增强窗格中,如何生成调试信息?
    lr 自带的例子,如何进行关联,通过代码的函数进行实现
    lr11 录制脚本时候,无法自动启动ie,查了网上很多方法都未解决?
    loadrunner11 录制脚步不成功,在录制概要出现“No Events were detected”,浮动窗口总是显示“0 Events”,解决办法
    loadrunner11 安装及破解教程来自百度文库
    安装loadrunner11 ,出现如下错误如何解决?
    回收站数据删除了,如何进行恢复?
    网管工作方面——————打印机删除了然后开机重启他依然存在,如何解决
    Windows 不能在 本地计算机 启动 SQL Server 服务 错误代码126
    Sorry, the page you are looking for is currently unavailable. Please try again later. Nginx
  • 原文地址:https://www.cnblogs.com/funmary/p/11608511.html
Copyright © 2011-2022 走看看