對問題“為什麼執行softirq時不能被搶佔?”的解答

來源:互聯網
上載者:User

1.首先,在irq_exit中調用do_softirq前已經退掉了preempt_count中的HARDIRQ_MASK,因此softirq此時如果不在preempt_count加上SOFTIRQ_MASK位還是會被搶佔的,我們看到softirq是在硬體中斷後執行的,因此如果硬體中斷是任意內容相關的話那麼softirq也是任意上下文,我們知道任意上下文下的睡眠或者調度會使得被中斷的進程不確定而且對被中斷的進程不公平,因此 softirq也不能睡眠,這也是一個約定,但是此時在未進入softirq的處理前卻是可以被搶佔的,因為硬體中斷處理已經完成,軟體中斷是相對不急的,因此僅在此時它可以被搶佔,然而一旦進入do_softirq的話,那麼softirq邏輯就又開始在這個被中斷的進程的上下文大做文章了,因此不能被搶佔,也不能調度,原因和上述硬體中斷一樣。

2.至於SOFTIRQ_MASK位,它是防止非強制中斷被重入而設定的,看看do_softirq中有個local_bh_disable,就是它遞增了preempt_count的SOFTIRQ_MASK位,使得在退出此次softirq處理前不能再進入,另外它也保證了在執行softirq的時候不被搶佔。

3.如果就到我上面說的為止,一切顯得很合理,但是我們知道softirq是不急的動作,如果沒完沒了的執行它的話,那麼對被中斷的進程仍然不公平,畢竟softirq一直在此進程上下文執行著,於是你說的softirqd就出來了,核心專門開了一個softirq服務線程來處理非強制中斷,我們看到在do_softirq(void)中:

int max_restart = MAX_SOFTIRQ_RESTART; //最大的softirq執行次數

if (pending && --max_restart) //如果沒有到最大次數,繼續執行

goto restart;

...

if (pending) //如果在執行上次softirq途中又pending了新的softirq請求並且已經不能再繼續執行softirq了,那麼喚醒softirqd吧。

wakeup_softirqd();

就是這樣的,上面的if(pending)判斷以及喚醒softirqd的邏輯在於不能給鼻子上臉,給了softirq MAX_SOFTIRQ_RESTART的執行機會就夠意思了,如果還有請求,抱歉,本次進程還忙著呢,不能再幫你了,你還是去請求softirqd吧,人家是專業的執行softirq的。做事不能太霸道了,softirq在硬體中斷完成後獲得執行機會,而且還遞增了被中斷進程的 preempt_count導致不能搶佔,這不但給當前進程增加不確定性,還導致了別的就緒進程無法搶佔當前被中斷的進程,這樣十分不好。

4.linux 巧妙的處理了中斷和效能的關係,你不是說中斷中不能睡眠並且不能執行太久嗎?那麼好我引入了非強制中斷softirq,如果softirq中能睡眠並且能長期佔用cpu那還不是和沒有引入一樣嗎?那麼好,linux又引入了softirqd,乾脆給它一個進程上下文。

5.注意,softirq的執行函數不能主動睡眠,但是在softirqd中卻是可以被搶佔的,睡眠和搶佔是兩個概念,前者主動後者被動。而且不能睡眠是在softirq的處理函數中,可以搶佔是在softirq外,在執行過程中還是不能搶佔的。

aha,說了這麼多有點羅嗦了,總結一下:

softirq不能被搶佔是因為它有可能在任意進程上下文執行,所謂搶佔必須在確定上下文中執行,不能睡眠也是因為它可能在任意上下文執行。至於softirqd只是為了不使softirq長期佔用cpu而提出的一個手段而已,應該這麼認為:以 softirq為主,以ksoftirqd為輔。

如此給你帶來的問題也同樣困擾了linux核心的開發人員們,於是工作隊列就出來了...下文太精彩,閃!

接下來又回郵件問:

>> 因此僅在此時它可以被搶佔,然而一旦進入do_softirq的話,那麼softirq邏輯就又開始在這個被中斷的進程的上下文大做文章了,因此不能被搶佔,也不能調度,原因和上述硬體中斷一樣。
這裡在do_softirq之前都可以被搶佔了..在進入do_softirq後的話,更加可以的啊.  為什麼進入do_softirq時要禁止呢?
>> 5.注意,softirq的執行函數不能主動睡眠,但是在softirqd中卻是可以被搶佔的,睡眠和搶佔是兩個概念,前者主動後者被動。而且不能睡眠是在softirq的處理函數中,可以搶佔是在softirq外,在執行過程中還是不能搶佔的。
用softirqd核心線程處理softirq時,完全是進程的上下文了.  為什麼還不能主動睡眠,以及在執行過程中就搶佔呢?

我的回答:

這裡在do_softirq之前都可以被搶佔了..在進入do_softirq後的話,更加可以的啊.  為什麼進入do_softirq時要禁止呢?
答: 進入do_softirq之前是核心的控制機制,有確定的行為,但是一旦進入你自己的softirq處理函數,那裡面怎麼執行就只有你自己知道了,比如你 搶了一把鎖,然後做事,核心此時根本不知道你做了些什麼,為了不使事情混亂不可收拾,比如你在佔有鎖時被搶佔了就會有問題,於是核心約定不允許搶佔 softirq。
用softirqd核心線程處理softirq時,完全是進程的上下文了.  為什麼還不能主動睡眠,以及在執行過程中就搶佔呢?
答:是進程上下文了,但是softirq並不是都在擁有進程內容相關的softirqd中執行,更多的要在硬體中斷後緊接著執行,那時它就是任意上下文了,引入softirqd的目的僅僅是不想讓softirq過多的佔據任意上下文,這其實是最大約束原則。
其實不要把softirq想得太神秘,它其實和硬體中斷機制在代碼上是統一的。

然後又問:

謝謝...
第二問題是基本明白了..也猜到了.呵呵.
第一個問題,在加鎖時,spin_lock()其實會禁止搶佔的.
我不想深究了.就理解成核心的約定了.為了儘快的返回被中斷的進程.

我的回答:

呵呵,深究起來確實會沒有完的,比如加鎖就一定禁用搶佔嗎,要加的不是自旋鎖呢?呵呵,不說了。其實理解linux的最好方法就是調試而不是深入 代碼細節,我以前初涉核心的時候就總進入一些死胡同,比如在一個地方spin_lock,然後我就為找不到unspin_lock而茶飯不思,後來才發現 是別的檔案裡面unspin_lock了,呵呵。在調試核心前一定要先瞭解核心的架構,其實linux核心設計得相當好的。我在張江,有時間一定交流交流,呵呵...

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.