前幾天在公司收到一題analyze performance的issue
後來比對了前後兩份log,看到kworker這些threads兩份行為不太一樣,有一份的kworker一直wake up然後preempt cpu resource,看了很欠揍,但我也不知道kworker到底是三小,所以上網查了一下跟trace code QQ
(雖然這題issue最後”應該”不是kworker的問題XD)
在kernel space中,driver都不太傾向自己創建一個thread去處理自己的任務,所以workqueue在這裡起了很大的作用,workqueue會收集各式各樣不同的driver丟過來的工作,可以節省很多resource(一個共享經濟的概念),透過process context的模式來處理這些work。
有個東西跟workqueue很像的概念叫tasklet,但它屬於interrupt context,如果今天driver來的事情很急且很小的話就適合tasklet,這樣比較貼近interrupt的使用。但不急不趕甚至要做的事情比較多就可以用workqueue,畢竟workqueue屬於process,是可以接受被scheduler排程的,甚至是sleep。
下面是一些名詞介紹。
work: 託付要執行的任務。
workqueue: 擺放工作的queue,蠻好理解的XD。
work_pool: worker工人的集合代表,一個類似ASUS Talent pool的概念XD。-
worker: kernel創建出來的worker,worker會從workqueue,去拉work出來做,如果沒有任何工作worker會先idle一段時間再進入sleep,工人的數量kernel會依據work的數量做動態的增減。
Data Struct
這邊只貼這個惹
struct work_struct { atomic_long_t data; struct list_head entry; //workqueue的list work_func_t func; //工作 #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif }; struct delayed_work { struct work_struct work; struct timer_list timer; /* target workqueue and CPU ->timer uses to queue ->work */ struct workqueue_struct *wq; int cpu; };
把work加入workqueue的方式好像有兩種,如下:
INIT_WORK(_work, _func) => schedule_work(_work)
INIT_DELAYED_WORK(_work, _func) =>schedule_delayed_work(_work)
前面都是做work初始化的動作,後面是把work加入workqueue,第二種是希望這個work可以延遲一段時間在執行,延遲的時間大概跟他DS中的timer有關係。
之後就交給worker來處理了吧?,看到kworker醒來大概是同事的code裡面有一直丟work的樣子,那時候trace code好像有看到struct work的variable…
這篇先打這樣好了,最近快把自己操死了,上週騎自行車昨天又跑了快九公里的慢跑(雖然今天只跑了四公里多XD),之後再看看要打啥,HIDL好像真的蠻多人看,幾乎天天都有人看。