Linux System Calls' Forum, #5:(第96號系統服務) sys_getpriority

jollen 發表於 October 19, 2006 9:07 PM

nice() 是用來變更 process 優先序(priority)的 system call 也是最古老的一個,sys_getpriority()sys_setpriority() 則是取代 sys_nice() 的新實作,今天我們先討論一下 'sys_getpriority'。

96 sys_getpriority linux/kernel/sys.c
類別:Systems
原型宣告:long sys_getpriority(int which, int who);
用途說明:取得 process 的排程優先序(Priority)。
Kernel (2.6.11 or above) 實作:
/*
 * Ugh. To avoid negative return values, "getpriority()" will
 * not return the normal nice-value, but a negated value that
 * has been offset by 20 (ie it returns 40..1 instead of -20..19)
 * to stay compatible.
 */
asmlinkage long sys_getpriority(int which, int who)
{
	struct task_struct *g, *p;
	struct user_struct *user;
	long niceval, retval = -ESRCH;

	if (which > 2 || which < 0)
		return -EINVAL;

	read_lock(&tasklist_lock);
	switch (which) {
		case PRIO_PROCESS:
			if (!who)
				who = current->pid;
			p = find_task_by_pid(who);
			if (p) {
				niceval = 20 - task_nice(p);
				if (niceval > retval)
					retval = niceval;
			}
			break;
		case PRIO_PGRP:
			if (!who)
				who = process_group(current);
			do_each_task_pid(who, PIDTYPE_PGID, p) {
				niceval = 20 - task_nice(p);
				if (niceval > retval)
					retval = niceval;
			} while_each_task_pid(who, PIDTYPE_PGID, p);
			break;
		case PRIO_USER:
			user = current->user;
			if (!who)
				who = current->uid;
			else
				if ((who != current->uid) && !(user = find_user(who)))
					goto out_unlock;	/* No processes for this user */

			do_each_thread(g, p)
				if (p->uid == who) {
					niceval = 20 - task_nice(p);
					if (niceval > retval)
						retval = niceval;
				}
			while_each_thread(g, p);
			if (who != current->uid)
				free_uid(user);		/* for find_user() */
			break;
	}
out_unlock:
	read_unlock(&tasklist_lock);

	return retval;
}

Jollen 的說明

讓我們來看一下 system call service - 'sys_getpriority' 的程式實作。首先是 sys_getpriority() 的參數:whichwho,這二個參數對應到 getpriority() which who 參數;如果您不是很清楚 which/who 的話,請參閱前幾天的日記

我們拿底下的程式片斷來討論:

	switch (which) { /* 請看 1. */
		case PRIO_PROCESS: /* 請看 2. */
			if (!who) /* 請看 2. */
				who = current->pid;
			p = find_task_by_pid(who); /* 請看 3. */
			if (p) { /* 請看 4. */
				niceval = 20 - task_nice(p); /* 請看 5. */
				if (niceval > retval)
					retval = niceval;
			}
			break;
		...
	}

說明如下:

  1. 判斷 which 參數,假設我們想要取得 process 的 priority,那麼 which 的值就是 PRIO_PROCESS
  2. which = PRIO_PROCESS,則 who 的值就是 process ID。因為 who 不應該為 0,所以如果 who 是 0 的話,就指定為 current 的 PID。
  3. find_task_by_pid() 是 kernel API,用來取得 PID 的 process descriptor。
  4. 如果 p 不是 NULL,就呼叫 task_nice(),取得 process 的「nice 值」,然後傳回 nice 值。
  5. kernel 的 nice 值範圍為 [-20..19],但 user-space 的 nice 值是 [40,1],所以要做換算:[20-(-20)..20-19] = [40..1]。

喔!要取得 process priority 的 kernel 實作看起來還挺簡單的。我們又學到了:

  • kernel API - find_task_by_pid():傳入 PID,取得該 process 的 process descriptor。
  • kernel API - task_nice():傳入 process descriptor,取得該 process 的 priority(nice 值)。
TIP
  • 所謂的「nice 值」就是 process 的優先序(優先等級、priority)。

 

跟上我們的腳步:請讀以下的文章,再看這篇日記!

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

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