2023-2024-1 20232801 刘莹《Linux内核原理与分析》第三周

实验三:Mykernel实验

1、进入Shell终端 

输入如下代码:

$ cd ~/LinuxKernel/linux-3.9.4
$ rm -rf mykernel
$ patch -p1 < ../mykernel_for_linux3.9.4sc.patch
$ make allnoconfig
$ make
$ qemu -kernel arch/x86/boot/bzImage 

代码分析:

patch -p1 < ../mykernel_for_linux3.9.4sc.patch: 应用名为mykernel_for_linux3.9.4sc.patch的补丁到当前目录下的文件系统中,该补丁文件会修改源代码文件。

make allnoconfig:使用默认配置生成配置文件.config,该配置文件将会编译出所有可用的内核模块。

make:运行make命令编译内核,生成可引导的Linux内核镜像

qemu -kernel arch/x86/boot/bzImage:使用qemu虚拟机运行生成的内核镜像文件bzImage。这将启动虚拟机并加载内核镜像。

2、搭建内核

搭建起来的内核启动效果如下:

内部代码解释:在Linux-3.9.4内核源代码根目录下进入mykernel目录,可以看到QEMU窗口输出的mymain.c和myinterrupt.c的代码。

进入mymain.c:函数my_start_kernel(void)函数,每执行100000次要输出“my_start_kernel here i”。

进入myinterrupt.c:可以看出mymain.c中的代码在不停地被执行,同时有一个中断处理程序的上下文环境,周期性地产生时钟中断信号,能够触发mykernel.c中的my_timer_hander(void)函数。

这样就模拟了一个带有时钟中断的x86CPU。

3、关键代码分析

1.mypcb.h头文件,用来定义进程控制块

2.mymain.c是mykernel内核代码的入口,负责初始化内核的各个组成部分

3.myinterrupt.c中断处理和进程调度

#关键代码
if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */
    {//save current scene
     /* switch to next process */
     asm volatile(	
         "pushl %%ebp\n\t" /* 压栈,保存当前ebp到堆栈*/
         "movl %%esp,%0\n\t" /* 保存当前ESP到当前PCB中 */
         "movl %2,%%esp\n\t" /* 将下一个进程的堆栈栈顶值存到ESP寄存器 */
         "movl $1f,%1\n\t" /* s保存当前进程的Eip值,下次恢复进程时取这里的值 */	
         "pushl %3\n\t" /*压栈 */
         "ret\n\t" /* 出栈标号1到eip寄存器 */
         "1:\t" /*标号1,也就是next进程开始执行的位置 */
         "popl %%ebp\n\t" /*恢复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\n                >>>process %d running!!!<<<\n\n",prev->pid,next->pid,next->pid);

  }
    else  /*next该进程第一次被执行*/

    {
        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)
     );
    }
    return;	
}//end of my_schedule

4、总结

(1)堆栈相关的寄存器和堆栈操作

  • ESP(栈顶指针寄存器)
  • EBP(基址指针寄存器):基址指针(指向栈顶),在C语言中用作记录当前函数调用的基址。
  • EAX:用于暂存一些数值,函数返回值默认使用EAX寄存器存储并返回给上一级调用函数。
  • EIP:指示将要执行的下一条指令在存储器中的地址。(总是指向某一条指令的地址)
  • CS(代码段寄存器)
  • push 压栈,栈顶地址减少四个字节
  • pop 出栈,栈顶地址增加四个字节
  • call 函数调用,调用一个地址。将当前CS:EIP的值压入栈顶,CS:EIP指向被调用函数的入口地址。
  • ret 函数返回,从栈顶弹出原来保存在这里的CS:EIP的值,放入CS:EIP中去。
  • enter 用来建立函数堆栈
  • leave 用来撤销函数堆栈

(2)Make:Make是一个用于自动化编译的工具,通过读取Makefile文件来确定代码之间的依赖关系,并根据需要编译这些文件。Makefile是一个包含了编译规则的文本文件,它描述了源代码、目标文件和可执行文件之间的关系。

qemu:一个虚拟化工具,它允许在一个宿主机上模拟运行不同体系结构的操作系统.它提供了一个虚拟机监控程序(VMM),并能够模拟处理器、设备和内存等关键组件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值