`
cloudtech
  • 浏览: 4646528 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

linux2.6.29 CFS调度详细分析(二)

 
阅读更多

上次主要讲了CFS调度的基本原理,并且没有分析有唤醒和进程迁移时候的调度流程,所以本文主要从内核中几个重要的调度点来详细的分析一下调度的基本流程,主要以流程图的形式给出。

内核中主要有以下几个重要的切入点:
(1)tick相关,即时钟中断

这就是上篇文章中讲的每次中断中,更新vruntime的整个过程,可以理解为是在中断的上半部分做的,很显然我们会想到前一篇文章中讲到的检查TIF_NEED_SCHED位并显示调用schedule()的地方就是中断的下半部分了,为了更好的理解我把中断的整个处理流程也做了个流程图(以时钟中断为例)

(这些流程图很大的,如果看不清可以下载下来放大看,应该相当清晰)

与中断相关的部分,我会在以后的文章里详细介绍,在这里就不具体接讲解了。

现在来总结一下这个切入点的整个过程:

当来一个时钟中断的时候,概括来说内核做了两个操作(参见上图中)

(1)do_timer():它主要来更新系统的时间

(2)update_progress_times():一方面去执行我们上面谈到的scheduler_tick(),另一方面他又去触发一个软中断

执行完上面几个步骤后,时钟中断就要返回了,因为其他的任务留给软中断做了。具体怎么做我会在中断一部分在分析。我们来看看中断返回时的一段代码:

call do_IRQ
jmp ret_from_intr#执行完do_IRQ后跳到ret_from_intr

ret_from_intr:

..............
cmpl $USER_RPL, %eax#判断返回用户态还是内核态
jb resume_kernel# not returning to v8086 or userspace

ENTRY(resume_userspace)
..............

jne work_pending
jmp restore_all

ENTRY(resume_kernel)
..........

need_resched:
movl TI_flags(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl #检查TIF_NEED_SCHED有没有被置位
jz restore_all
testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all
call preempt_schedule_irq #在这里显示调用了schedule()
jmp need_resched

到这里我们已经跟踪了在时钟中断里面的一个完整的调度过程。

(2)当前进程主动放弃CPU


既然是主动放弃,直接主动调用schedule()就行了,内核里面的很多地方都是这么做的,只要搜一下schedule的调用点就会看到。下面是从schedule()开始的一个调用


流程图

:

总结一下执行的流程:

(1)清除TIF_NEED_SCHED

(2)判断一下当前进程应该被继续设置为TASK_RUNNING状态,如果不是的话就把它从运行队列中删除

(3)看一下当前运行队列是否还有可运行进程,没有的话,调用idle_balance(cpu, rq)平衡负载

(4)把当前进程放回运行队列,并设置当前进程的指针为空。

(5)选择下一个进程作为当前进程

(6)判断如果当前进程不等于选择的进程的话,就进行进程切换,执行swtich_to,这部分将在下次讲解。

先说这么多,因为有很多细节我也不怎么理解,下面提出几个问题,希望能和大家一块讨论:

(1)schedule()函数中的这段代码及其展开

if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)){
/*prev->state >0 即当前进程处在stopped状态下,而且可抢占的情况下*/
if (unlikely(signal_pending_state(prev->state, prev)))
prev->state = TASK_RUNNING;/**/
else
deactivate_task(rq, prev, 1);/*从红黑树中删除prev*/
switch_count = &prev->nvcsw;

这部分的意思是如果当前进程还需要呆在运行队列中就设置其prev->state = TASK_RUNNING,否则把它从

红黑树中删除。

问题一:继续留在运行队列的那个判断条件具体是什么意思?

if (unlikely(signal_pending_state(prev->state, prev)))

猜测应该是,TASK_INTERRUPTIBLE这种状态时,可随时接受信号来继续运行。

问题二: 如果不留在运行队列就要从红黑树种删除,跟踪删除函数最后到了dequeue_entity()的这段代码


/*清除伙伴*/
clear_buddies(cfs_rq, se);
/*大部分情况下二者是相等的,不执行,
因为当前进程一直就不在运行队列中
问题的关键是什么情况下执行呢?*/
if (se != cfs_rq->curr)
__dequeue_entity(cfs_rq, se);


这个判断条件是什么意思?se不就是当前进程吗?什么情况下这个判断条件才能成立,最好能有个具体的例子。

我是这么想的,大部分情况下se = cfs_rq->curr,那么出队操作就不执行,因为当前进程是不在运行队列中的,这一点可以从新选择一个进程来运行的时候要先把它出列得到印证,具体可见pick_next_task().



分享到:
评论

相关推荐

    linux2.6.29

    linux2.6.29kernel

    linux2.6.29的qq2440补丁文件

    linux2.6.29的qq2440补丁文件

    linux2.6.29源码

    linux2.6.29完整linux源代码,对于学习linux内核的人来说是很好的,通过sourceinsighe可以完整的阅读linux2.6.29,对深入学习内核工作原理的也很有帮助

    linux2.6.29 driver

    linux2.6.29 driver

    运动图像检测系统 mini2440 linux2.6.29 motion

    运动图像检测系统由uboot2008.10+linux2.6.29+nfsrootfs+motion组成,摄像头的硬件为市场上任意一款。开发板为mini2440.

    基于linux-2.6.29在mini2440上移植boa服务器的详细步骤

    这是整理的一份关于boa服务器移植的详细步骤,我已经将它移植在linux2.6.29中并在mini2440上的得到实现,希望对做嵌入式web开发的您有所帮助。

    Linux2.6.29内核映像文件For友善之臂mini2440

    为友善之臂mini2440编译好的内核映像文件zImage,内核版本号2.6.29,交叉编译工具arm-linux-gcc-3.4.5

    linux-2.6.29在mini2440上的内存底层初始化学习笔记

    linux-2.6.29在mini2440上的内存底层初始化学习笔记

    rt73-2.6.29-linux-driver

    rt73 linux driver支持对应linux2.6.29kernel

    linux-2.6.29.tar.bz2

    linux-2.6.29.tar.bz2

    linux-2.6.29.tar.gz

    linux2.6版内核,有一定的学习价值,大多数开发板基于此版本进行系统移植,因为官网下载的太慢也不好找,所以传上来供有需要的朋友下载。

    Linux设备模型分析

    本文主要是对设备模型及涉及的sysfs文件系统、event事件、udev等概念基于Linux2.6.29的分析。

    Linux2.6.9源代码

    这个资源是Linux2.6.29的源代码。比较不错

    goldfish-android-goldfish-2.6.29

    goldfish-android-goldfish-2.6.29 goldfish-android-goldfish-2.6.29

    linux-2.0.30---33

    不过我都写了版本号的范围,总体范围从linux1.0.tar到linux-2.6.29.tar,推荐朋友们用ultraedit去打开比较方便阅读,当然是自己喜欢的阅读器就行了,也不一定用这个,不过这个阅读起来的确比较好用的!

    linux-1.1.23.tar

    索下载你所需要的版本号的内核源代码范围从linux-1.0.tar到linux-2.6.29.tar,推荐朋友们用ultraedit去打开比较方便阅读,当然是自己喜 欢的阅读器就行了,也不一定用这个,不过这个阅读起来的确比较好用的!

    linux 字符设备驱动

    用于linux的字符设备驱动程序的编写,适用于linux2.6.29内核的mini2440开发板

    linux-1.1.29.tar

    索下载你所需要的版本号的内核源代码范围从linux-1.0.tar到linux-2.6.29.tar,推荐朋友们用ultraedit去打开比较方便阅读,当然是自己喜 欢的阅读器就行了,也不一定用这个,不过这个阅读起来的确比较好用的!

    linux-2.3.0.tar

    不过我都写了版本号的范围,总体范围从linux1.0.tar到linux-2.6.29.tar,推荐朋友们用ultraedit去打开比较方便阅读,当然是自己喜欢的阅读器就行了,也不一定用这个,不过这个阅读起来的确比较好用的!

    linux-1.1.45.-linux-1.1.83

    索下载你所需要的版本号的内核源代码,有时候一个一个的上传太麻烦了,我做了压缩,不过我都写了版本号的范围,总体范围从linux-1.0.tar到linux-2.6.29.tar,推荐 朋友们用ultraedit去打开比较方便阅读,当然是自己...

Global site tag (gtag.js) - Google Analytics