1 什么是進程凍結
進程凍結技術(freezing of tasks)是指在系統hibernate或者suspend的時候,將用戶進程和部分內核線程置于“可控”的暫停狀態。
2 為什么需要凍結技術
假設沒有凍結技術,進程可以在任意可調度的點暫停,而且直到cpu_down才會暫停并遷移。這會給系統帶來很多問題:
(1)有可能破壞文件系統。在系統創建hibernate image到cpu down之間,如果有進程還在修改文件系統的內容,這將會導致系統恢復之后無法完全恢復文件系統;
(2)有可能導致創建hibernation image失敗。創建hibernation image需要足夠的內存空間,但是在這期間如果還有進程在申請內存,就可能導致創建失敗;
(3)有可能干擾設備的suspend和resume。在cpu down之前,device suspend期間,如果進程還在訪問設備,尤其是訪問競爭資源,就有可能引起設備suspend異常;
(4)有可能導致進程感知系統休眠。系統休眠的理想狀態是所有任務對休眠過程無感知,睡醒之后全部自動恢復工作,但是有些進程,比如某個進程需要所有cpu online才能正常工作,如果進程不凍結,那么在休眠過程中將會工作異常。
3 代碼實現框架
凍結的對象是內核中可以被調度執行的實體,包括用戶進程、內核線程和work_queue。用戶進程默認是可以被凍結的,借用信號處理機制實現;內核線程和work_queue默認是不能被凍結的,少數內核線程和work_queue在創建時指定了freezable標志,這些任務需要對freeze狀態進行判斷,當系統進入freezing時,主動暫停運行。
kernel threads可以通過調用kthread_freezable_should_stop來判斷freezing狀態,并主動調用__refrigerator進入凍結;work_queue通過判斷max_active屬性,如果max_active=0,則不能入隊新的work,所有work延后執行。
標記系統freeze狀態的有三個重要的全局變量:pm_freezing、system_freezing_cnt和pm_nosig_freezing,如果全為0,表示系統未進入凍結;system_freezing_cnt》0表示系統進入凍結,pm_freezing=true表示凍結用戶進程,pm_nosig_freezing=true表示凍結內核線程和workqueue。它們會在freeze_processes和freeze_kernel_threads中置位,在thaw_processes和thaw_kernel_threads中清零。
fake_signal_wake_up函數巧妙的利用了信號處理機制,只設置任務的TIF_SIGPENDING位,但不傳遞任何信號,然后喚醒任務;這樣任務在返回用戶態時會進入信號處理流程,檢查系統的freeze狀態,并做相應處理。
任務主動調用try_to_freeze的代碼如下:
static inline bool try_to_freeze_unsafe(void)
{
if (likely(!freezing(current))) //檢查系統是否處于freezing狀態
return false;
return __refrigerator(false); //主動進入凍結
}
static inline bool freezing(struct task_struct *p)
{
if (likely(!atomic_read(&system_freezing_cnt))) //系統總體進入freezing
return false;
return freezing_slow_path(p);
}
bool freezing_slow_path(struct task_struct *p)
{
if (p-》flags & PF_NOFREEZE) //當前進程是否允許凍結
return false;
if (pm_nosig_freezing || cgroup_freezing(p)) //系統凍結kernel threads
return true;
if (pm_freezing && !(p-》flags & PF_KTHREAD)) //系統凍結用戶進程
return true;
return false;
}
進入凍結狀態直到恢復的主要函數:bool __refrigerator(bool check_kthr_stop)
{
。..
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE); //設置進程為UNINTERRUPTIBLE狀態
spin_lock_irq(&freezer_lock);
current-》flags |= PF_FROZEN; //設置已凍結狀態
if (!freezing(current) ||
(check_kthr_stop && kthread_should_stop())) //判斷系統是否還處于凍結
current-》flags &= ~PF_FROZEN; //如果系統已解凍,則取消凍結狀態
spin_unlock_irq(&freezer_lock);
if (!(current-》flags & PF_FROZEN)) //如果已取消凍結,跳出循環,恢復執行
break;
was_frozen = true;
schedule();
}
。..。..
}
4 參考文獻
(1) http://www.wowotech.net/linux_kenrel/suspend_and_resume.html
(2) http://www.wowotech.net/linux_kenrel/std_str_func.html
(3) kenrel document: freezing-of-tasks.txt
編輯:hfy
-
內核
+關注
關注
3文章
1372瀏覽量
40280 -
Linux
+關注
關注
87文章
11293瀏覽量
209340 -
進程
+關注
關注
0文章
203瀏覽量
13960
發布評論請先 登錄
相關推薦
評論