nice() 是用來變更 process 優先序(priority)的 system call,nice() system call 叫用(invoke)的 system call 實作常式為 sys_nice。sys_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