Linux 进程之进程优先级

108 阅读3分钟

1. 前言

在 Linux 操作系统中,并非所有的进程都具有相同的重要性。有些进程的重要性天然就比其他进程的重要性要高一些。举个例子,你正在使用 Ubuntu 桌面办公。你的前台运行者一个 Office 进程正在处理文档,后台运行着一个批处理程序正在两个目录之间拷贝数据。此时,你一定不希望出现批处理程序占用了过多了的 CPU 资源,导致的 Office 办公工序卡顿。为了解决这个问题,Linux Kernel 中引入了进程优先级的概念。优先级越高的进程,越受到 CPU 的青睐。本文从优先级的表示方法以及计算方法,简要介绍一下 Linux Kernel 中进行的优先级机制。

2. 优先级的表示

进程优先级在用户空间内核空间采用了不同的表示方法。在用户空间中,可以通过nice命令设置进程的静态优先级。nice的值在 -20 到 19 之间。nice的值越小,优先级越高

在内核空间则是另一番景象。内核使用了更简单的范围 0 到 139 来表示静态优先级。同样也是值越小,优先级越高。其中 0 到 99 的值是专门给实时进程使用的,而用户空间nice的值则映射到 100 到 139。

3. 进程优先级的定义

上面我们讲了优先级的表示,但是没有介绍这个优先级定义在哪个位置。进程优先级是进程的一个属性,我们很容易会想到它应该是进程描述符(task_struct)的一个字段。实际情况也很接近了,进程优先级确实是存放进程描述符(task_struct)中,但是不是一个字段,而是四个字段。

struct task_struct {
        ...
  // 动态优先级
	int prio;
  // 静态优先级
	int static_prio;
  // 普通优先级
	int normal_prio;
  // 实时进程专用优先级
	unsigned int rt_priority;
}

其中的rt_priority属性是拥有实时调度策略的进程(也即是实时进程)专用的优先级字段。而其他三个则为普通进程拥有的优先级字段。

4. 普通进程优先级的计算

上面介绍了,普通进程的由三个属性表示。那么问题来了,它们是怎么组合起来表示进程的优先级的呢?

/*
 * Calculate the current priority, i.e. the priority
 * taken into account by the scheduler. This value might
 * be boosted by RT tasks, or might be boosted by
 * interactivity modifiers. Will be RT if the task got
 * RT-boosted. If not then it returns p->normal_prio.
 */
static int effective_prio(struct task_struct *p)
{
	p->normal_prio = normal_prio(p);
	/*
	 * If we are RT tasks or we were boosted to RT priority,
	 * keep the priority unchanged. Otherwise, update priority
	 * to the normal priority:
	 */
	if (!rt_prio(p->prio))
		return p->normal_prio;
	return p->prio;
}

effective_prio是调度器计算进程有效优先级的方法。当进程是普通进程时,会通过normal_prio计算出优先级并返回。而normal_prio函数会返回普通进程的static_prio静态优先级。当进程是实时进程或者是优先级提高到实时优先级的普通进程,则返回prio动态优先级。

5. 参考资料

查看文章原文