赶尸艳谈国语影音先锋:进程切换内核抢占概念

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 13:15:17
aoface
(stranger)
06-09-25 19:55
关于进程切换内核抢占概念的不解,请各位指教

最近学OS,有一处不明,特发贴请教一下坛里的兄弟姐妹:)

首先有几句话是课本上的:
1.内核态运行的进程是不可以被抢占的。
2.只有下列三种情况可以发生进程切换:
(1)进程进入等待态
(2)中断返回但此时进程不是最具备有CPU的资格
(3)系统调用返回但此时进程不是最具备有CPU的资格

[请问1.上述的(2)(3)情况中,是不是在核心态运行的进程被调度出CPU了?那么是否和第1条冲突?
2.(2)(3)所指是否是时间片到达被迫退出CPU呢?
3.我描述一个流程,大家看一下对不对。一个用户态进程运行着,时钟中断来了,进入核心态(请问此时进程是处于核心态运行吗?如果不是,不过不知如何描述进程这时的状态),转向时钟中断处理程序,发现这个进程的时间片到了,于是要把它请出CPU到就绪状态,这个时候发生的是进程切换没错吧,此时调度一个新进程到运行态,此时是不是同时也返回了用户态呢?
]

一口气问了这么多,希望能有大侠指点一二,谢谢。

Iambitious
(stranger)
06-09-26 09:47
Re: 关于进程切换内核抢占概念的不解,请各位指教

linux是支持内核抢占的。(编译内核的时候选择抢占模式)
linux分为两种抢占:
1.用户抢占:
发生在系统调用返回,和中断返回的时候。
2.内核抢占:
发生在中断返回,显式调用schedule()。

你所说的那种情况对应的是用户抢占。
用户进程与内核进程是完全不同的,一个用户进程是通过系统调用来调用内核的函数,而内核进程是本身执行一个内核函数,内核进程永远不会被换出内核空间。

aoface
(stranger)
06-09-26 17:47
Re: 关于进程切换内核抢占概念的不解,请各位指教

谢谢楼上的回答。此外还有个问题想问问:一个进程处于核心态运行下被中断打断了,此时的进程处于什么状态?(没有发生进程切换)

leviathan
(addict)
06-09-27 10:45
Re: 关于进程切换内核抢占概念的不解,请各位指教

处理中断的时候, 被打断的进程还是RUNNING态。 中断处理不改变被打断进程的状态的,只有在处理完毕中断,要返回的时候,如果发生重新调度, 才可能改变进程状态。

huihuizxc
(stranger)
06-09-27 14:51
Re: 关于进程切换内核抢占概念的不解,请各位指教

下面是自己对有些原代码的分析

分析四 LINUX进程调度

对于一些频繁要执行的代码 效率非常的重要,

1、每个进程在task_struct中和调度有关的保存信息:
• policy 将被应用于本进程的调度策略。有两种Linux进程:普通的和实时的。实时进程拥有比其他进程都要高的优先级。如果有一个实时进程准备好了运行,它总是先运行。实时进程可以有两种高度策略:“轮转(round robin)”法和“先进先出(first in first out)”。在轮转法调度中每个可运行的实时进程依次运行;而在先进先出法中,实时进程按它们进入运行队列的顺序依次运行,并且该顺序永不会改变。
• nice 调度器将给予进程的优先级。它也是进程被允许运行时可以运行的时间量(在jiffies中)。可以通过系统调用的方法和renice命令来改变进程的优先级。
• rt_priority Linux支持实时进程,并且它们在调度时拥有比系统中其他非实时进程更高的优先级。这个字段使调度器可以给每个实时进程一个相对优先级。实时进程的优先级
可以用系统调用改变。
• counter 此进程允许的运行时间量(在jiffies中)在第一次运行时被置成nice的值,然后在每个时钟“滴答”中递减。
• need_resched 告诉调度器是否应该进行调度了。在以下几种情况下会被设置成1,一时钟中断中发现当前进程的时间片已经用完,二从系统返回当用户空间的时候 处于礼让,改变调度策略或者有优先级别更加高的进程被唤醒(比当前进程),三是一个进程改变调度策略和礼让

2、调度策略:
1>、总体上继承了UNIX以优先级为基础的调度。即每个进程有一个代表运行资格的权值,然后系统挑选权值最高的进程投入运行。在运行过程中,当前进程的资格随时间而递减(在时钟中断中),这样一来在下次的调度中那些权值低的可能比当前运行的要高了,从而得到了运行的可能。如果在中间没有出现调度(强制引起的一些调度,比如中断),那么等到它的权值为0时(时间片用光了),系统就会进行一次调度。如果所有可运行进程的权值都是0那么系统将进行一次进程运行资格的重新计算,资格的计算主要是以优先级为基础。
2>、局部上又分为3种调度策略,也可以说是2种实时和非实时
非实时 SCHED_OTHER:普通进程 适合交互式分时进程。

实时 SCHED_RR SCHED_FIFO:
SCHED_FIFO: 一旦调度中被选种,它会一直运行,直到自愿让出CPU为止,如果进程运行时间比较短,那没什么问题,如果运行时间比较长,那么处于同优先级的进程将会一直等待,根本就没机会得到运行。所以说这种调度策略适用于 时间性要求比较强,但是 每次运行时间比较段的进程,比如对于一个外设的read数据,需要时间性要求要快,但是执行比较短。
SCHED_RR:采用轮流,可以说是补充了FIFO的同优先级进程得不到运行的情况,对于这种调度,当时间片用完时,会把当前进程放到进程等待队列末尾,那么同优先级别的进程就得到了运行的机会了。

非实时进程的权值确定: 剩余的时间配额 + (20 - p->nice),其中nice是UNIX沿用下来的负向优先级,取值返回是 19~ -20,以-20为最高,所以经过转换以后是1到40 40为最高。如果是内核线程或者用户空间与当前进程相同而不需要切换用户空间,那么会得到+1的奖励。要注意的是当剩余的时间配额为0的时候 进程的权值被强制设置成0,这样系统就可以进行调度了,上面已经提到如果全部就绪的进程权值为0那么就要进行重新计算,重新计算包括了那些未就绪的进程 计算公式
p->counter = (p->counter>>1) + NICE_TO_TICKS(p->nice),这样对于未就绪的非实时进程得到了提升优先级别的机会,当然对于实时进程的优先级别是没有影响的。但明显可以看出无论这么提升最终也是不会达到NICE_TO_TICKS(p->nice)的2陪的。

实时进程的权值确定 1000+p->rt_priority,其中1000是基数,rt_priority(rt就是real time的意思)即实时进程的优先级,而时间配额p->counter的当前值对实时进程不起作。对于SCHED_RR,当p->counter为0的时候会把当前进程放到队列的末尾,nice对实时进程的权值也是没有影响的,但是对于SCHED_RR的时间配额大小有关系,因为时间配额的大小是根据p->counter = (p->counter>>1) + NICE_TO_TICKS(p->nice) 计算的。而对于SCHED_FIFO本身就无所谓时间配额(因为即时间片用完了,当前进程的位置还是不变,仍旧在首位),除非有高优先级的进程,否则也不会退让,所以都无关。
实时进程比非实时进程有着高很多的优先级,在调度过程中,如果有实时进程准备就绪,那么非实时进程根本就得不到运行的机会。
这里需要补充的一点是 如果在调度是发现有2个或者以上的进程具有相同的优先级,那么就调用先进入的那个进程。

3、调度方式:
分为2种,自愿调度和强制性调度。
1>、自愿调度就是调用函数schedule(),随时都可以发生,这个函数是在系统空间调用的,在应用空间可以用pause()得到同样的效果。
还有二种情况 一是是礼让,调用函数sched_yield()。具体方法是:将current->policy中的SCHED_YIELD标志置为1,然后把need_resched设置成表示要进行调度。在调度过程中会把SCHED_YIELD这个标志清楚为0。使用sched_yield()的情况一般就是等待一个事件的到来,但又不想使自己进入睡眠状态,比如等待执行一个IO的完毕,或者等待一个标志位的到来等。礼让不改变当前进程在可执行进程队列中的位置,所以如果当前进程本身的优先级别是很高很高的 比如是实时进程,那么调度后运行的还是当前进程,这样就失去了意义,所以说使用礼让的进程基本上要other调度的进程(普通进程)。
二是改变调度策略和参数系统,函数是sched_setscheduler()的作用是改变进程的调度策略。上面2中情况发生调度的的必要条件也是 从系统空间返回到用户空间的前夕。

2>、强制调度,发生在从系统空间返回到用户空间的前夕,但是有条件的,所以说是有条件的剥夺。比如说下面的情况:当唤醒一个进程,发现这个进程的优先级比当前的要高,那么就会出现一次调度。
还有一种情况就是发生在时钟中断里面,当检查到到前进程运行时间过长的时候发生,前面已经提到。
这里需要提到一点强制调度是有条件的,也就是必须发生在从系统空间返回到用户空间的前夕。比如打个比方:进程调用一个内核函数处于内核态时,这个时候产生了一个中断,而此时系统已经知道这个进行的时间片已经用完,中断服务程序执行完毕后返回,因为返回后还是处于内核态,所以此时是不会发生调度的,那么在什么时候发生调度呢?要等到进程调用的内核函数返回。也就是必须发生在从系统空间返回到用户空间的前夕,这样一来就存在一个问题,如果这个时候一个高优先级别的进程在等待,将会被延迟响应(在抢占式调度中没这个现象)。

4、抢占调度:
Linux 2。6下支持抢占调度,原理是 如果内核不是在一个中断处理程序中,并且不在spinlock保护的代码中,就认为可以 安全 的进行进程切换。 实际上他在不可抢占的linux的基础上做了2件事情 在释放spinlock时候或者当中断返回时,如果当前执行的进程的need_resched被标记(需要调度),则进行抢占式调度。

具体可以看进程调度原理相关部分代码:
函数Schedule() kernel/sched.c


aoface
(stranger)
06-09-30 10:11
Re: 关于进程切换内核抢占概念的不解,请各位指教

谢谢大家的指教,学习了。