Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Linux2.6內核進程調度系列--scheduler_tick()函數3.更新普通進程的時間片,

Linux2.6內核進程調度系列--scheduler_tick()函數3.更新普通進程的時間片,

編輯:關於android開發

Linux2.6內核進程調度系列--scheduler_tick()函數3.更新普通進程的時間片,


RT

	/**
	 * 運行到此,說明進程是普通進程。現在開始更新普通進程的時間片。
	 */
	 /* 首先遞減普通進程的時間片計數器。如果用完,繼續執行以下操作 */
	if (!--p->time_slice) {
		/**
		 * 既然用完了,就將當前進程從活動集合中摘除。
		 */
		dequeue_task(p, rq->active);
		/**
		 * 當然,當前進程既然已經過期,就必須設置重新調度標志,
		 * 以便在中斷返回前調用schedule選擇另外一個進程來運行。
		 */
		set_tsk_need_resched(p);
		/**
		 * 更新當前進程的動態優先級。
		 * effective_prio根據當前進程的static_prio和sleep_avg字段,
		 * 計算進程的動態優先級。
		 */
		p->prio = effective_prio(p);
		/**
		 * 重填進程的時間片
		 */
		p->time_slice = task_timeslice(p);
		/**
		 * 既然當前進程的一個時間片已經用完,
		 * 當然就需要清除first_time_slice標志了。
		 */
		p->first_time_slice = 0;

		/**
		 * 如果本地運行隊列的expired_timestamp為0,表示過期進程集合為空。
		 * 並且當前進程馬上就會變成過期進程,
		 * 那麼將當前jiffies賦給expired_timestamp
		 * expired_timestamp表示當前隊列中,過期隊列中
		 * 最老進程被插入過期隊列的時間。
		 */
		if (!rq->expired_timestamp)
			rq->expired_timestamp = jiffies;
		/**
		 * 把當前進程插入過期進程集合或者活動進程集合。
		 * TASK_INTERACTIVE判斷當前進程是否是一個交互式進程。
		 * TASK_INTERACTIVE宏檢查運行隊列中的第一個過期進程
		 * 的等待時間是否已經超過1000個時鐘節拍乘以運行隊列
		 * 中的可運行進程數+1,如果是返回1.
		 * EXPIRED_STARVING表示如果當前進程的靜態優先級大於
		 * 過期進程的靜態優先級,也返回1.
		 */
		if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) {
			/**
			 * 當前進程不是交互式進程,或者過期隊列中有優先級
			 * 更高的進程,那麼將當前進程插入到過期隊列。
			 */
			enqueue_task(p, rq->expired);
			/**
			 * 如果當前進程是過期隊列中優先級最高的低,
			 * 就更新過期隊列的最高優先級。
			 */
			if (p->static_prio < rq->best_expired_prio)
				rq->best_expired_prio = p->static_prio;
		} else
		/* 進程是交互式進程,並且比過期隊列中所有進程的靜態優先級高,
		* 那麼就將它加到活動隊列中。這實際上是對交互式進程的優待。 */
			enqueue_task(p, rq->active);
	}
	else {/* 普通進程的時間片還沒有用完,需要進一步檢查是否時間片太長 */
		
		/**
		 * 檢查當前進程的時間片是否太長,因為對於交互式進程來說,
		 * 它時間片用完後,可能會再插入到活動隊列,可能導致這種
		 * 進程的時間片特別長。
		 */
		if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
			p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
			(p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
			(p->array == rq->active)) {

			requeue_task(p, rq->active);
			set_tsk_need_resched(p);
		}
	}

1.effective_prio函數計算進程的動態優先級。

普通進程除了靜態優先級,還有動態優先級,其值的范圍是100(最高優先級)~139(最低優先級)。動態優先級是調度程序在選擇新進程來運行的時候使用的數。它與靜態優先級的關系用下面的經驗公式表示:

bonus是范圍從0-10的值,值小於5表示降低動態優先級以示懲罰,值大於5表示增加動態優先級以示獎賞。bonus的值依賴於進程過去的情況,說得更准確一些,是與進程的平均睡眠時間相關。

#define CURRENT_BONUS(p) \
	(NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
		MAX_SLEEP_AVG)

/**
 * 讀取current的static_prio和sleep_avg字段,並根據公司計算進程的動態優先級。
 */
static int effective_prio(task_t *p)
{
	int bonus, prio;

	if (rt_task(p))
		return p->prio;

	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;

	prio = p->static_prio - bonus;
	if (prio < MAX_RT_PRIO)
		prio = MAX_RT_PRIO;
	if (prio > MAX_PRIO-1)
		prio = MAX_PRIO-1;
	return prio;
}

2.TASK_INTERACTIVE宏判斷進程是不是一個交互式進程。

粗略地講,平均睡眠時間是進程在睡眠狀態所消耗的平均納秒數。注意,這絕對不是對過去時間的求平均值的操作。例如,在TASK_INTERRUPTIBLE狀態與在TASK_UNINTERRUPTIBLE狀態所計算出的平均睡眠時間是不同的。而且,進程在運行的過程中平均睡眠時間遞減。最後,平均睡眠時間永遠不會大於1s。

平均睡眠時間也被調度程序用來確定一個給定進程是交互式進程還是批處理進程。更明確地說,如果一個進程滿足下面的公式,就被看作是交互式進程:

它相當於下面的公式:

#define DELTA(p) \
	(SCALE(TASK_NICE(p), 40, MAX_BONUS) + INTERACTIVE_DELTA)

#define TASK_INTERACTIVE(p) \
	((p)->prio <= (p)->static_prio - DELTA(p))

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved