進程凍結和解凍的本質

在我前面的文章中已經介紹了內核中的進程凍結技術,進程凍結存在的意義以及它的實現架構,沒有看過的童鞋可以點擊如下鏈接過去瀏覽:
https://blog.csdn.net/rikeyone/article/details/103182748

看過此文的人可能又會產生一些新的疑問,一個進程如果被凍結了,那麼它到底在做什麼呢?處於什麼狀態呢?這也是我當時產生的疑問,經過RTFSC,就記錄了本文,對該問題進行一些解答,本文的內容基於Linux-4.0。

凍結狀態

通過前文,我們知道當系統休眠時,是會對用戶進程發送凍結信號的,同時也會對內核線程發送凍結的信號(姑且當做是一種信號吧)。而實際的凍結操作並不是在suspend中執行的,suspend只會發送信號,而是各自進程接收到信號後各自對自己進行凍結操作,實際最終運行的是如下內核函數:

bool __refrigerator(bool check_kthr_stop)
{
	/* Hmm, should we be allowed to suspend when there are realtime
	   processes around? */
	bool was_frozen = false;
	long save = current->state;  // --- 1

	pr_debug("%s entered refrigerator\n", current->comm);

	for (;;) {
		set_current_state(TASK_UNINTERRUPTIBLE); // --- 2

		spin_lock_irq(&freezer_lock);
		current->flags |= PF_FROZEN;
		if (!freezing(current) ||               // --- 3
		    (check_kthr_stop && kthread_should_stop()))
			current->flags &= ~PF_FROZEN;
		spin_unlock_irq(&freezer_lock);

		if (!(current->flags & PF_FROZEN))     // --- 4
			break;
		was_frozen = true;
		schedule();                            // --- 5
	}

	pr_debug("%s left refrigerator\n", current->comm);

	/*
	 * Restore saved task state before returning.  The mb'd version
	 * needs to be used; otherwise, it might silently break
	 * synchronization which depends on ordered task state change.
	 */
	set_current_state(save);     // --- 6

	return was_frozen;
}

1.保存本進程凍結前的狀態到save

2.設置本進程爲D狀態(TASK_UNINTERRUPTIBLE)

3.判斷當前進程是否需要執行freeze凍結

4.如果經過前面的條件判斷,不應該對本進程執行凍結,那麼就break掉

5.如果滿足凍結條件,那麼執行schedule(),該函數會把要睡眠的進程從rq中移除

6.跳出循環後恢復進程的狀態爲save保存的值

通過以上的分析,我們可以看出所謂的進程凍結,它的本質實際上就是設置進程進入不可中斷的休眠狀態(TASK_UNINTERRUPTIBLE)。

解凍狀態

從上面可以看出一個進程進入了凍結狀態,那麼它就會在schedule()之後進入睡眠狀態,所謂的解凍就是把睡眠狀態的進程喚醒,恢復之前的狀態後繼續運行。
先看一下解凍處理的第一步,喚醒操作:

void __thaw_task(struct task_struct *p)
{
	unsigned long flags;

	spin_lock_irqsave(&freezer_lock, flags);
	if (frozen(p))
		wake_up_process(p);
	spin_unlock_irqrestore(&freezer_lock, flags);
}

該函數是在resume時執行的操作,其中的關鍵動作就是wake_up_process,在喚醒操作中需要掃描所有被凍結的進程並且喚醒它們。

從上面的__refrigerator函數可以看到,凍結的進程從schedule()中被喚醒之後,它依然在for循環當中,但此時該進程已經是一個解凍的狀態了,通過第3步檢測時就會跳過凍結操作,因此就從循環中break出來,然後就可以恢復save狀態繼續運行了。

因此解凍的本質就是喚醒所有被凍結的進程,恢復他們的運行狀態,並且繼續運行原來的任務。


參考鏈接:

https://blog.csdn.net/rikeyone/article/details/103182748
http://www.wowotech.net/pm_subsystem/237.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章