在我前面的文章中已經介紹了內核中的進程凍結技術,進程凍結存在的意義以及它的實現架構,沒有看過的童鞋可以點擊如下鏈接過去瀏覽:
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