linux内核时间片轮询,《Linux操作系统分析》之分析精简的Linux的内核中断和时间片轮询...

本篇文章分析的是一个经过精简后的Linux系统,通过对中断和时间片轮询的分析。来说明系统中进程的启动和进程的切换机制。

相关知识

首先关于这篇文章会介绍一些用到的知识。

一、程序运行时堆栈的变化以及相关的知识,我已在 《Linux操作系统分析》之分析计算机如何启动以及如何工作运行这篇博客中分析过,请没看过的同学点击链接。

二、进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。如果有同学对进程和线程不是太明白的话。请参考阮一峰老师的 进程与线程的一个简单解释。

三、中断简单的来说就是在你做一件事的时候,被打断去执行其他的事情。举个日常生活中的例子,比如说我正在厨房用煤气烧一壶水,这样就只能守在厨房里,苦苦等着水开——如果水溢出来浇灭了煤气,有可能就要发生一场灾难了。等啊等啊,外边突然传来了惊奇的叫声“怎么不关水龙头?”于是我惭愧的发现,刚才接水之后只顾着抱怨这份无聊的差事,居然忘了这事,于是慌慌张张的冲向水管,三下两下关了龙头,声音又传到耳边,“怎么干什么都是这么马虎?”。伸伸舌头,这件小事就这么过去了,我落寞的眼神又落在了水壶上。门外忽然又传来了铿锵有力的歌声,我最喜欢的古装剧要开演了,真想夺门而出,然而,听着水壶发出“咕嘟咕嘟”的声音,我清楚:除非等到水开,否则没有我享受人生的时候。请参考下面的文章 点击链接。

四、时间片轮询算法。这是计算机调度的方法之一。通过为程序分配指定的时间,来控制程序执行的时间。通过时间片的概念实现同步的,也就是程序的并发。举个例子:当你在打台球的时候,一般是两个人进行游戏。当有三个人的时候,每人五个球,如果你打进球了,就继续打下一杆。否则就轮到下一个人打。在这个例子中如果都没打进球的话,三个人是轮流评分时间执行,但是如果打进球的话,就相当于把打进球者的优先级提高,可以再执行一次。

接下来我用一个例子来进行分析。这个例子所用到的代码,已经环境的配置信息等可以在 mykernel中获得。

分析过程

下面的是mypcb.h中的一部分代码。用来模仿系统中存放进程的管理和控制信息的数据结构即进程控制块(PCB Process Control Block)。

54e4fd129864be64cf90ff0797d6dbfa.png ip:记录CPU的地址(即%eip的值)。

sp:栈顶地址。

结构体PCB中为记录程序的信息,用来保存现场和恢复现场的数据。

my_schedule函数用来模拟调度函数。

在mykernel.c中包含一下函数:

void my_process(void);

模拟程序

unsigned long get_rand(int );

得到一个随机数

void sand_priority(void)

模拟出进程的优先级

void __init my_start_kernel(void)

模拟内核程序

以上有所函数的执行过程大概如下:

运行mykernel进入到该函数(如何知道进入mykernel可以参考 为什么主引导记录的内存地址是0x7C00),首先执行以下的代码:

e7ce66bff99f3b3929f482f37d6f5dc3.png  对第一个进程的PCB进行赋值。

/*fork more process */

for(pid=1;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

}

上面的代码将第一个进程进行复制,而后修改一些基本信息。

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*/

);

上面的汇编代码,将进行操作栈和实现操作eip。此后进入到my_process函数执行进程的任务。

通过myinterrupt.c中的my_timer_handler函数可以对my_need_sched = 1;进行赋值,以此来模拟进程是否需要调度。如果需要调度的时候,进入到my_schedule(); 。在这里保存了当前的进程和接下来要执行的进程,通过分析剩下进程的优先级,来选择出一个优先级高的进程作为下一个需要执行的进程。

然后通过判断next进程是否你一执行来选择:(1)执行next进程(2)将next置为可执行,在选择新的进程进行执行。返回到my_process函数执行进程的任务。

如此重复该过程,实现进程的切换机制。

执行过程截图如下:

6b23f402a28b1bf85bcbfc3efc8bb147.png  

89488b200805379fb628d69d45552145.png  

3a51d91a02cfabdd769358e46d4188cc.png  

7f4fd5d52356e15644140194b8357cfa.png  

b7220a84fd4f27db895ce9cb79f30ebc.png  总结

简单来讲,操作系统启动的时候,通过写到BIOS中的主引导项,选择进入系统。进入到系统之后,通过重复循环,等待执行进程。如果有多个进程的时候,操作系统通过调度算法为选中的进程分配系统资源。如果需要进行进程的切换的话,通过中断机制进行打断程序的执行,而后通过保存现场和恢复现场来恢复需要执行的进程。在这里也只是简单的介绍了操作系统的中断和进程切换。如果有不对的地方,请大家指教,相互学习,共同进步。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值