现在的位置: 首页 > 综合 > 正文

交互式进程和批处理进程

2013年08月03日 ⁄ 综合 ⁄ 共 3314字 ⁄ 字号 评论关闭
调度程序还提供了一种机制以支持交互进程

    The scheduler provides one additional aide to interactive tasks: If a task is sufficiently interactive, when it exhausts its timeslice it will not be inserted into the expired array, but instead reinserted back into the active array.
    调度程序还提供了一种机制以支持交互进程:如果一个进程的交互性非常强,那么当它的时间片用完后,它会被再次放置到活动数组而不是过期数组。
    Timeslice recalculation is provided via the switching of the active and the expired arrays. Normally, as processes exhaust their timeslices, they are moved from the active array to the expired array. When there are no more processes in the active array, the two arrays are switched: The active becomes the expired, and the expired becomes the active. This provides O(1) timeslice recalculation. It also provides the possibility that an interactive task can become runnable but fail to run again until the array switch occurs because the task is stuck in the expired array. Reinserting interactive tasks back into the active array alleviates this problem. The task does not run immediately, but is scheduled round robin with the other tasks at its priority. The logic to provide this feature is implemented in scheduler_tick(), which is called via the timer interrupt:
    重新计算时间片是通过活动数组与过期数组之间的切换来进程的。一般进程在用尽它们的时间片后,都会被移至过期数组,当活动数组中没有剩余进程的时候,这两个数组被就会被交换;活动数组变成过期数组,过期数组替代活动数组。这样操作提供了时间复杂度为O(1)的时间片时间片重新计算。但在这个交换发生之前,交互性很强的一个进程有可能已经处于过期数组中了,当它需要交互的时候,它却无法执行,因为必须等到数组交换发生为止才可执行。将交互式的进程重新插入到活动数组可以避免这种问题。但该进程不会被立即执行,它会和优先级相同的进程轮流着被调度和执行。该逻辑在scheduler_tick()中实现,该函数会被定时器中断调用:

struct task_struct *task;
struct runqueue *rq;
task = current;
rq = this_rq();
if (!--task->time_slice) {
    dequeue_task(p, rp->active);
    set_tsk_need_resched(task);
    task->prio = effective_prio(task);
    if (!TASK_INTERACTIVE(task) || EXPIRED_STARVING(rq))//(1)
        enqueue_task(task, rq->expired);
    else
        enqueue_task(task, rq->active);
}

//(1)     如果进程task交互性不是很强(真),那么该进程被放入过期进程队列中;
    如果进程task的交互性很强(假),但是有饥饿进程存在(真),那么该进程被放入过期进程队列;
    如果进程task的交互性很强(假),并且没有饥饿进程存在(假),那么该进程被放入活跃进程队列。
    First, the code decrements the process's timeslice and checks whether it is now zero. If it is, the task is expired and it needs to be inserted into an array, so this code first checks whether the task is interactive via the TASK_INTERACTIVE() macro. This macro computes whether a task is "interactive enough" based on its nice value. The lower the nice value (the higher the priority) the less interactive a task needs to be. A nice +19 task can never be interactive enough to be reinserted.
    首先,这段代码减小进程时间片的值,再看它是否为0。如果是的话就说明进程的时间片已经耗尽,需要把它插入到一个数组中(具体插入到哪个数组还需要进一步判断),所以该代码先通过TASK_INTERACTIVE()宏来查看这个进程是不是一个交互型的进程。该宏主要基于进程的nice值来判定它是不是一个“交互性十足”的进程。nice值越小(优先级越高),越能说明该进程交互性越高。一个nice值为+19的进程交互性表现的再强,它也不可能--不会(在其时间片用完之后)被重新加入到活动数组中去。
    Conversely, a nice -20 task would need to be a heavy processor hog not to be reinserted.A task at the default nice value, zero, needs to be relatively interactive to be reinserted, but it is not too difficult. Next, the EXPIRED_STARVING() macro checks whether there are processes on the expired array that are starvingthat is, if the arrays have not been switched in a relatively long time. If they have not been switched recently, reinserting the current task into the active array further delays the switch, additionally starving the tasks on the expired array. If this is not the case, the process can be inserted into the active array. Otherwise, it is inserted into the expired array, which is the normal practice.
    而一个nice值为-20的进程要想不被重新加入(也就是不被当作交互性很强的进程),只用拼命地占用处理器才行。一个拥有默认优先级的进程,需要表现出一定的交互性才能被重新加入,但这通常很容易。接着,EXPIRED_STARVING()宏负责检查过期数组内的进程是否处于饥饿状态---是否已经有相对较长的时间没有发生数组切换了。如果最近一直没有发生切换,那么再把当前进程放置到活动数组会进一步拖延切换---过期数组内的进程会更加饥饿。只要不发生这两种情况,进程就会被重新放置在活动数组里。否则,进程会被放入过期数组里,这也是最常见的一种操作。

抱歉!评论已关闭.