Linux System Calls' Forum, #4:(第34號系統服務) sys_nice

jollen 發表於 October 15, 2006 12:55 AM

nice() 是用來變更 process 優先序(priority)的 system call,nice() system call 叫用(invoke)的 system call 實作常式為 sys_nicesys_nice 服務常式(service routine)是 Linux 排程(scheduling)相關的服務常式中最基本(也是最古老)的一個。

34 sys_nice linux/kernel/sched.c
類別:Scheduling
原型宣告:long sys_nice(int increment);
用途說明:變更 process 的優先序。
Kernel (2.6.11 or above) 實作:
/*
 * sys_nice - change the priority of the current process.
 * @increment: priority increment
 *
 * sys_setpriority is a more generic, but much slower function that
 * does similar things.
 */
asmlinkage long sys_nice(int increment)
{
	int retval;
	long nice;

	/*
	 * Setpriority might change our priority at the same moment.
	 * We don't have to worry. Conceptually one call occurs first
	 * and we have a single winner.
	 */
	if (increment < -40)
		increment = -40;
	if (increment > 40)
		increment = 40;

	nice = PRIO_TO_NICE(current->static_prio) + increment;
	if (nice < -20)
		nice = -20;
	if (nice > 19)
		nice = 19;

	if (increment < 0 && !can_nice(current, nice))
		return -EPERM;

	retval = security_task_setnice(current, nice);
	if (retval)
		return retval;

	set_user_nice(current, nice);
	return 0;
}

Jollen 的說明

首先,讓我們先看一下 NICE(2) 的內容:

NAME
       nice - change process priority

SYNOPSIS
       #include 

       int nice(int inc);

DESCRIPTION
       nice  adds  inc  to  the nice value for the calling pid.  (A large nice
       value means a low priority.)  Only the superuser may specify a negative
       increment, or priority increase.

參數 inc 是所要改變的 priority 數量,inc 可以是正數也可以是負數。正數表示 priority 變多(多加上 inc,表示  low priority),若要提升 priority,inc 只要指定為負數即可;根據 NICE(2) 的說明,只有 superuser 才能指定負數,也就是把提高優先序。

nice() 會把 process 的 priority 變更為 "priority+ inc"。

sys_nice() 的實作

以下是 sys_nice() service routine 的原型:

long sys_nice(int increment)

increment 就是前面所提到的 inc 參數(透過 system call 機制傳遞,並非函數呼叫傳值)。increment 的範圍被 kernel 限定在 [40,-40] 的範圍內:

	if (increment < -40)
		increment = -40;
	if (increment > 40)
		increment = 40;

所以如果呼叫 nice() 時,指定的優先改變量超過 [40,-40] 時,是得不到預期效果的。sys_nice 接著先把 process 的 "priority" 數值轉算成 "nice" 值,然後再加上 increment(因為 increment 是一個 "nice" 值,不是 "priority" 值):

	nice = PRIO_TO_NICE(current->static_prio) + increment;

得到的 "nice" 值,必須限定在 [19,-20] 的範圍內:

	if (nice < -20)
		nice = -20;
	if (nice > 19)
		nice = 19;

再來,如果 increment 小於 0,也就是 user 的 "nice" 值是負的,那就要檢查是不是可以變更此 process 的 "priority":

	if (increment < 0 && !can_nice(current, nice))
		return -EPERM; 

不過這裡的重點是 can_nice() 所呼叫的 kernel API - capable(),並非 can_nice() 本身,再追一下 can_nice() 的原始碼可以找到這段:

capable(CAP_SYS_NICE)

capable() 用來檢查 process 的 "capability",不過我們先在這裡略過這個主題。

Process capability 若允許變更 priority,就修改 process 的 priority,否則 return -EPERM

更多關於 sys_nice()

sys_nice() 目前大概是為了要向後相容而持續存在於 Linux 原始碼裡,目前已經推薦改用 sys_setpriority() 服務常式了。因此在 Linux programming 上,我們也要改用 setpriority() system call 來取代 nice()。以下是 GETPRIORITY(2):

NAME
       getpriority, setpriority - get/set program scheduling priority

SYNOPSIS
       #include 
       #include 

       int getpriority(int which, int who);
       int setpriority(int which, int who, int prio);
TIP

  "priority" 表示 process 的優先序,數字越大表示優先序越低;"nice" 指的是要改變的 priority 量,例如 -10 表示要把 priority 減少 10,即提高優先序。

--jollen

作者/陳俊宏
http://www.jollen.org

Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue

您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw