關於郵件列表乙個問題的解釋

2021-08-25 01:29:29 字數 2002 閱讀 7154

問題:在 exit_mm() 中為什麼要 atomic_inc(&mm->mm_count) 呢? 並沒有對應的dec。

解答:首先要明白,對於乙個可以被釋放記憶體的程序也就是說乙個擁有mm_struct的程序來說,它的task_struct中的mm欄位和active_mm欄位是一樣的,這個在fork時,copy_mm中就決定了,接下來解釋這個問題:

在exit_mm中:

atomic_inc(&mm->mm_count); //這裡遞增了引用計數,你說對了,沒有dec但是inc了,多了一次inc,那麼就要多一次dec

bug_on(mm != tsk->active_mm); //保證mm和tsk->active_mm一樣

task_lock(tsk);

tsk->mm = null; //注意這裡將tsk->mm設定為null

up_read(&mm->mmap_sem);

enter_lazy_tlb(mm, current);

clear_freeze_flag(tsk);

task_unlock(tsk); //第一次dec

然後注意在do_exit呼叫exit_mm之後,最終會呼叫schedule將這個退出程序切出去,因此最終釋放task_struct將在新程序切到執行之後再進行,那麼看context_switch中:

oldmm = prev->active_mm; //這裡的prev就是那個退出程序,其active_mm就是上面的mm,由此可見上面的atomic_inc就是為了這裡

if (unlikely(!prev->mm)) else

switch_mm(oldmm, mm, next); //如果下乙個不是核心執行緒,那麼就切換mm_struct,也就是切換頁表

if (unlikely(!prev->mm)) { //這裡就是關鍵,標記為*

prev->active_mm = null;

rq->prev_mm = oldmm;

上面的標記為*的if判斷很重要,prev->mm什麼時候為假呢?有兩種情況,第一就是前乙個程序是核心執行緒,第二就是前乙個程序是使用者程序但是已經退出,我們這裡的情況是第二種情況,只有在這種情況下rq->prev_mm被賦值為退出程序的active_mm,而這個和退出程序的mm一樣,記住此時mm的引用計數在exit_mm由於被inc了變成了1,那麼安全切換了以後在finish_task_switch中判斷rq->prev_mm不為空從而被釋放。這個解釋很合理,但是和tlb重新整理的懶惰模式沒有關係,而只是保證了退出程序的pgd在mm切換之前不被釋放,那麼第二種情況就是要說懶惰模式相關的,如果下乙個程序是核心執行緒,那麼進入:

if (unlikely(!mm)) { //如果下乙個程序的mm為空就說明下乙個程序是核心執行緒

next->active_mm = oldmm;

atomic_inc(&oldmm->mm_count); //又遞增了乙個引用計數

enter_lazy_tlb(oldmm, next); //進入懶惰模式

可以看到,不但釋放不了了mm,還又一次遞增了它的引用計數,此時引用計數為2,可是不要急,不但進入了上面的if,連後面的if (unlikely(!prev->mm))也會進入,那麼在切換以後還是會在mmdorp中遞減一次mm的引用計數,這樣這個核心執行緒保持了引用計數為1的mm,當核心執行緒被切換出去時,if (unlikely(!prev->mm))為真,因為核心執行緒沒有mm(也可以有),那麼在切換以後還是會呼叫mmdrop,此時mm被釋放,pgd被釋放,一切安然!

因此可以看出,linux對引用計數的設定是多麼巧妙啊,乙個mm_struct不但有users計數還有count計數,如果我設計的話,這倆肯定就合二為一了,linux的設計者考慮的真是細緻,users為0了count可以不為0,為何呢?users為0說明沒有程序使用了,可是count不為0說明排程器還要使用,前面說過,排程器在被排程的程序的上下文執行,排程器借用頁目錄,那麼就要保留頁目錄到排程器不用為止,另外,不但排程器要借用頁目錄,核心執行緒還可以借用之,這是為了提高效率,可以少一次切換開銷,核心認為少一次切換開銷比釋放乙個mm_struct帶來的收益要更有意義。

關於郵件列表乙個問題的解釋

問題 在 exit mm 中為什麼要 atomic inc mm mm count 呢?並沒有對應的dec。解答 首先要明白,對於乙個可以被釋放記憶體的程序也就是說乙個擁有mm struct的程序來說,它的task struct中的mm欄位和active mm欄位是一樣的,這個在fork時,copy...

關於上乙個問題的解釋

private functioninit void private function init voidtypeerror error 1034 強制轉換型別失敗 無法將 flash.display sprite 156b7b1 轉換為 mx.core.iuicomponent。而是在contain...

乙個關於iphone應用郵件功能的問題

郵件功能也許沒有太多需要說的,這裡要說的是有關郵件功能涉及到的一些細節問題。先看一段 void launchmailcomposer uibutton sender self presentmodalviewcontroller composer animated yes composer rele...