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 #includeint 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