《linux内核分析》第二次课 实验作业

潘聪  原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

这次的实验主要是研究线程调度中的主动调度。

---------------------------------------------

一、基础结构

(1)进程:在mypcb.h中,进程由ip(eip)和sp(esp)共同组成。

(2)进程控制块(PCB):进程号pid,状态(错误/运行中/停止运行),进程堆栈(包括内核栈和用户栈,此处合二为一了,详见[1]),进程,任务入口,通过next指针组成一个链表。

二、初始化(__init my_start_kernel)

生成零号进程:进程号0,状态运行,任务入口和ip为my_process的地址(此处将函数名作为指针使用,返回函数地址),sp设置为栈顶,链表next指向自身。

生成其他进程:进程号依次分配,入口与零号进程相同,状态为未运行,sp设置为各自的栈顶(每个进程维护一个自身的栈),使链表连成环状链表。

当前任务设定为零号进程。

asm代码段:

 1     asm volatile
 2     (
 3         "movl %1, %%esp\n\t" //set task[pid].thread.sp to esp
 4         "pushl %1\n\t" //push ebp
 5         "pushl %0\n\t" //push task[pid].thread.ip
 6         "ret\n\t" //pop task[pid].thread.ip to eip
 7         "popl %%ebp\n\t"
 8         :
 9         : "c" (task[pid].thread.ip), "d" (task[pid].thread.sp)
10     );

将零号进程的栈顶指针esp赋值给系统的esp,并将esp压栈(可以理解为ebp压栈),并将零号进程的ip压栈,并使用ret指令从该ip开始执行指令。

理论上,如果这些进程不退出的话,最后一行popl永远不会被执行。

三、主进程方法(my_process)

每个指令周期进行一次循环,每10000000此循环后打印当前运行进程的进程号两次;若进程调度标识为1,在两次打印期间执行调度函数。

四、调度句柄(my_timer_handler)

每次中断后开始运行该函数,累积1000次中断后将调度标识置为1,从而使主进程方法运行调度函数。

五、调度函数(my_schedule)

定义两个tPCB类型的指针,分别指向当前进程和下一个进程。针对下个进程的运行状态不同(运行中或其他)分为两段汇编代码进行对应的进程上下文切换。

1)下个进程正在执行:

 1 asm volatile
 2                 (
 3                         "pushl %%ebp\n\t" //save ebp
 4                         "movl %%esp, %0\n\t" //save esp
 5                         "movl %2, %%esp\n\t" //restore esp
 6                         "movl $1f, %1\n\t" // save eip |1f mean label 1
 7                         "pushl %3\n\t"
 8                         "ret\n\t" //restore eip
 9                         "1:\t" //next process start here
10                         "popl %%ebp\n\t"
11                         : "=m" (prev->thread.sp), "=m" (prev->thread.ip)
12                         : "m"(next->thread.sp), "m" (next->thread.ip)
13                 );

将ebp压栈,当前进程的sp记录esp,当前进程的ip记录label1的地址,当进程切换返回后将栈中原ebp的内容重新弹回到ebp中。

除此之外,还将当前进程设为下一进程,并打印切换文字。

2)下个进程未执行:

在执行汇编命令之前,先将下一进程状态设置为运行中,并将其设为当前进程。

执行的汇编代码与1)类似,在此不进行赘述。

------------------------------------------------------------------------------

最后,make后使用命令qemu -kernel arch/x86/boot/bzImage,生成图见下图:

--------------------------------------------

[1]从迷你型linux内核理解进度调度的原理http://itdreamerchen.com/%E4%BB%8E%E8%BF%B7%E4%BD%A0%E5%9E%8Blinux%E5%86%85%E6%A0%B8%E7%90%86%E8%A7%A3%E8%BF%9B%E7%A8%8B%E8%B0%83%E5%BA%A6%E7%9A%84%E5%8E%9F%E7%90%86/

时间: 2024-12-15 06:37:01

《linux内核分析》第二次课 实验作业的相关文章

《linux内核分析》第一次课 实验作业

解释main.c的汇编码的堆栈变化 实验截图如下图所示: 下面从main函数开始进行分析(三个可变数值从上到下分别为4,7,4): 不妨假设一开始为空栈,初始位置为0,ebp=esp,以下用行号进行标记 18:esp指向位置(1),位置(1)的值为esp的地址 19:使ebp指向与esp相同的地址(位置1) 20:esp指向位置(2) 21:位置(2)的值为7 22:调用f函数(标号):esp指向位置(3),位置(3)的值为eip的地址,将f的地址放到eip中 09:esp指向位置(4),位置(

魏昊卿——《Linux内核分析》第三周作业:Linux系统启动过程

魏昊卿——<Linux内核分析>第三周作业:Linux系统启动过程 一.实验部分 实验指导 使用实验楼的虚拟机打开shell 1 cd LinuxKernel/ 2 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img 内核启动完成后进入menu程序(<软件工程C编码实践篇>的课程项目),支持三个命令help.version和quit,您也可以添加更多的命令,对选修过<软件工程C编码实践篇>

linux内核分析第二周

网易云课堂linux内核分析第二周 20135103                王海宁 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 操作系统的核心功能就是:进程调度和中断机制,通过与硬件的配合实现多任务处理,再加上上层应用软件的支持,最终变成可以使用户可以很容易操作的计算机系统, my_timer_handler 函数会被内核周期性的调用,每调用1000次,就去将全局变量my_need_sched的值修

LINUX内核分析第二周学习总结:操作系统是如何工作的?

马启扬 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.函数调用堆栈 1. 小结:计算机是怎样工作的 三个法宝:存储程序计算机.函数调用堆栈.中断机制. 存储程序计算机工作模型,计算机系统最最基础性的逻辑结构. 函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能.(函数参数传递

Linux内核分析——第二周学习笔记

20135313吴子怡.北京电子科技学院 chapter 1 知识点梳理 (一)计算机是如何工作的?(总结)——三个法宝 ①存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: ②函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能: enter pushl %ebp movl %esp,%ebp leave movl %ebp,%esp popl %ebp 函数参数传递机制和局部变量存储 ③中

20135327郭皓——Linux内核分析第二周 操作系统是如何工作的

操作系统是如何工作的 上章重点回顾: 计算机是如何工作的?(总结)——三个法宝 存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: 函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能: enter pushl %ebp movl %esp,%ebp leave movl %ebp,%esp popl %ebp 函数参数传递机制和局部变量存储 中断,多道程序操作系统的基点,没有中断机制程序只能

linux内核分析第八次实验

20135118 罗鹏越 本周学习的是linux内核中的进程调度,之前我们在操作系统中有讲解进程调度的分类,以及一些调度算法.而linux中的进程调度有所不同,首先老师讲解了进程调度和进程调度的时机,所有的用户态进程都只能被调度,而内核线程可以主动调度,而进程调度的实现都是通过schedule函数,然后讲解了进程上下文所包含的信息,然后讲解了切换寄存器状态所使用的switch to函数,每一个部分都单独分析了.然后讲解了LINUX架构和执行过程.虽然在操作系统中讲解过了进程调度,但是这个讲解得更

linux内核分析第二四学习报告

学生  黎静 课程内容 计算机三大法宝 • 存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: • 函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能: • 中断,多道程序操作系统的基点,没有中断机制程序只能从头一直运行结束才有可能开始运行其他程序. 一.函数调用堆栈 1.堆栈 堆栈式C语言程序运行时必须的一个记录调用路径和参数的空间.包括: 函数调用框架 传递参数 保存返回地址(如eax)

linux内核分析第四次实验

实验步骤: 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用.本次实验中我使用第20号系统调用getpid()函数,用于取得进程识别码. C代码(getpid.c): #include <unistd.h> #include <stdio.h> int main() { pid_t pid; pid = getpid(); printf("pid = %d \n",pid); return 0; } 编译及运行结果见下图: 嵌入汇编代码getpi