溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何進行Linux Kernel iowait 時間的代碼原理分享

發(fā)布時間:2021-11-06 18:29:50 來源:億速云 閱讀:167 作者:柒染 欄目:建站服務(wù)器

這篇文章給大家介紹如何進行Linux Kernel iowait 時間的代碼原理分享,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

當task發(fā)生iowait的時候,內(nèi)核對他們的處理方法是將task切換出去,讓可運行的task先運行,而在切換出去前,會將其in_iowait設(shè)置為1,再次被喚醒的時候in_iowait被設(shè)置為原值。相關(guān)函數(shù)io_schedule,io_schedule_timeout,mutex_lock_io,mutex_lock_io_nested。

例如:

如何進行Linux Kernel iowait 時間的代碼原理分享

由此可見in_iowait表明了這個task是否在iowait。

另外要注意的是,這幾個切換函數(shù)除了mutex_lock_io,mutex_lock_io_nested會設(shè)置task運行狀態(tài)為TASK_UNINTERRUPTIBLE外,內(nèi)核在調(diào)用io_schedule,io_schedule_timeout前都會設(shè)置task運行狀態(tài)TASK_UNINTERRUPTIBLE。

在進程切換函數(shù)__schedule在切換task的時候,如果被切換出的task的in_iowait為真,則會對這個CPU的運行隊列rq結(jié)構(gòu)中的nr_iowait加1。

因為前面對task已經(jīng)被設(shè)置為TASK_UNINTERRUPTIBLE,則task需要被喚醒,對nr_iowait的減少操作也是在task喚醒函數(shù)來做的。

由此可見nr_iowait可以表明某CPU上是否有task在iowait,以及數(shù)量。

因為處于iowait的task是TASK_UNINTERRUPTIBLE狀態(tài),其并不在就緒隊列中,所以其也沒有被CPU負載均衡到其他CPU的可能,所以nr_iowait也不需要處理負載均衡問題。

當累加系統(tǒng)idle時間的時候,如果CPU的nr_iowait為真,也就是當前這個cpu有task在等待iowait,則記錄為iowait時間。

在打開NO_HZ的內(nèi)核中,相關(guān)代碼在update_ts_time_stats。

如何進行Linux Kernel iowait 時間的代碼原理分享

而沒打開的則在 account_idle_time。

如何進行Linux Kernel iowait 時間的代碼原理分享

當相關(guān)/proc/stat接口被訪問時,get_iowait_time就會訪問這個時間并返回。

綜上所述,iowait時間就是CPU idle時間,但是這時候CPU上不是完全沒TASK需要運行,而是休眠的task中有一個或者若干個是iowait的task。

當然idle和iowait的時候CPU上還有idle task。

最后推薦一篇阿里內(nèi)核組的文章作為擴展閱讀Kernel Documents/new iowait calculation (http://link.zhihu.com/?target=http%3A//kernel.taobao.org/index.php%3Ftitle%3DKernel_Documents/new_iowait_calculation)

比較有意思是這里:


+       wait_event_interruptible_hrtimeout(ctx->wait,

+                       aio_read_events(ctx, min_nr, nr, event, &ret), until);

無論超時值until是什么值,都會調(diào)用wait_event_interruptible_hrtimeout,雖然是hrtimer實時性已經(jīng)很高,但是在用來實際處理wait的宏__wait_event_hrtimeout可以看到hrtimer初始化使用的是:


hrtimer_start_range_ns(&__t.timer, timeout,\

       current->timer_slack_ns,\

       HRTIMER_MODE_REL);\

其中第三個參數(shù)current->timer_slack_ns是傳遞給hrtimer的觸發(fā)范圍,因為hrtimer實時性高,但是頻繁觸發(fā)系統(tǒng)顯然受不了,所以每次hrtimer觸發(fā)都會將時間范圍內(nèi)的timer都處理掉(見__hrtimer_run_queues)。所以timeout+current->timer_slack_ns才是設(shè)置的hrtimer的最后觸發(fā)時間,current->timer_slack_ns的默認值是50000,也就是代表50000納秒。也就是這個時鐘最久會在50000納秒后觸發(fā),當然也可能被之前的hrtimer觸發(fā)。

所以在wait_event_interruptible_hrtimeout中,一旦ctx->wait未能就緒,即使設(shè)置超時時間為0,也很可能要調(diào)用一次schedule,這導致iowait時間相差很大,也還很大幅度傷害了性能。

而這個問題也被5f785de588735306ec4d7c875caf9d28481c8b21進行了修復(fù),這段代碼改成了:



-       wait_event_interruptible_hrtimeout(ctx->wait,

-                       aio_read_events(ctx, min_nr, nr, event, &ret), until);

+       if (until.tv64 == 0)

+               aio_read_events(ctx, min_nr, nr, event, &ret);

+       else

+               wait_event_interruptible_hrtimeout(ctx->wait,

+                               aio_read_events(ctx, min_nr, nr, event, &ret),

+                               until);


從而在until為0的時候,直接調(diào)用aio_read_events。應(yīng)該就不會再有那么明顯的iowait問題了,另外也因此這個修復(fù)讓io_getevents的調(diào)用得到了超過百倍的性能提升。

當然這個iowait不夠精確的原因還是存在,一旦因為需要發(fā)生task切換,還是會有不夠精確的問題。

關(guān)于如何進行Linux Kernel iowait 時間的代碼原理分享就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI