国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 操作系統 > 正文

內核源碼分析之tasklet(基于3.16-rc4)

2024-06-28 13:25:05
字體:
來源:轉載
供稿:網友
內核源碼分析之tasklet(基于3.16-rc4)

tasklet是在HI_SOFTIRQ和TASKLET_SOFTIRQ兩個軟中斷的基礎上實現的(它們是在同一個源文件中實現,由此可見它們的關系密切程度),它的數據結構和軟中斷比較相似,這篇博文將分析tasklet的初始化過程。

1.和tasklet相關的數據結構

tasklet_vec和tasklet_hi_vec數組(kernel/softirq.c)

1 static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);2 static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);

第1行中為所有cpu創建了名為tasklet_vec數組,每個元素和一個cpu相關聯,數組元素類型為struct tasklet_head。第2行和第1行類似,創建出的tasklet_hi_vec數組存放的是每個cpu上優先級更高的tasklet小任務。下面看下struct tasklet_head結構體(kernel/softirq.c)。

1 struct tasklet_head {2     struct tasklet_struct *head;3     struct tasklet_struct **tail;4 };

內核會為每個cpu分配一個這樣的結構體變量,從而每個cpu都擁有一個小任務函數的鏈表。再看下結構體(kernel/softirq.c)。

1 struct tasklet_struct2 {3     struct tasklet_struct *next;4     unsigned long state;5     atomic_t count;6     void (*func)(unsigned long);7     unsigned long data;8 };

第1行next指向小任務鏈表下一個節點,第6行func變量指向了小任務函數。

2.tasklet初始化

小任務是基于HI_SOFTIRQ和TASKLET_SOFTIRQ兩個軟中斷來實現的。HI_SOFTIRQ所對應的軟中斷函數是tasklet_action,如下(kernel/softirq.c):

 1 static void tasklet_action(struct softirq_action *a) 2 { 3     struct tasklet_struct *list; 4  5     local_irq_disable(); 6     list = __this_cpu_read(tasklet_vec.head); 7     __this_cpu_write(tasklet_vec.head, NULL); 8     __this_cpu_write(tasklet_vec.tail, &__get_cpu_var(tasklet_vec).head); 9     local_irq_enable();10 11     while (list) {12         struct tasklet_struct *t = list;13 14         list = list->next;15 16         if (tasklet_trylock(t)) {17             if (!atomic_read(&t->count)) {18                 if (!test_and_clear_bit(TASKLET_STATE_SCHED,19                             &t->state))20                     BUG();21                 t->func(t->data);22                 tasklet_unlock(t);23                 continue;24             }25             tasklet_unlock(t);26         }27 28         local_irq_disable();29         t->next = NULL;30         *__this_cpu_read(tasklet_vec.tail) = t;31         __this_cpu_write(tasklet_vec.tail, &(t->next));32         __raise_softirq_irqoff(TASKLET_SOFTIRQ);33         local_irq_enable();34     }35 }

第6行中tasklet_vec數組中和本地cpu相關的元素的head域值,保存在list變量中,實際上把當前cpu的tastlet任務鏈表卸下來,list成為鏈表頭指針。第7,8行把tasklet_vec數組和本地cpu相關的元素的head域置為NULL,tail域指向head域。第11-26行用while循環執行所有的tasklet函數。第21行是tasklet函數的執行。第30-31行把執行之后的struct tasklet_struct鏈表節點重新掛到tasklet_vec數組中,由此可見裝tasklet函數的結構體不用程序員手動創建,由系統來提供。第32行重新設置軟中斷掩碼表的相應位。TASKLET_SOFTIRQ所對應的軟中斷函數是tasklet_hi_action,和tasklet_action執行過程類似,不再分析。

來看下tasklet_action函數初始化過程(kernel/softirq.c)。

 1 void __init softirq_init(void) 2 { 3     int cpu; 4  5     for_each_possible_cpu(cpu) { 6         per_cpu(tasklet_vec, cpu).tail = 7             &per_cpu(tasklet_vec, cpu).head; 8         per_cpu(tasklet_hi_vec, cpu).tail = 9             &per_cpu(tasklet_hi_vec, cpu).head;10     }11 12     open_softirq(TASKLET_SOFTIRQ, tasklet_action);13     open_softirq(HI_SOFTIRQ, tasklet_hi_action);14 }

第5-10行,初始化tasklet_vec和tasklet_hi_vec兩個數組的元素,使每個元素的tail域指向head域。cpu編號作為兩個數組的下標。第12-13行將負責處理tasklet任務的兩個軟中斷函數tasklet_action和tasklet_hi_action分別存入軟中斷數組softirq_vec[NR_SOFTIRQS]的相應元素中。來看下open_softirq函數(kernel/softirq.c)。

1 void open_softirq(int nr, void (*action)(struct softirq_action *))2 {3     softirq_vec[nr].action = action;4 } 

相信你一看就明白了,不用解釋了~

再看看tasklet的初始化過程(kernel/softirq.c):

1 void tasklet_init(struct tasklet_struct *t,2           void (*func)(unsigned long), unsigned long data)3 {4     t->next = NULL;5     t->state = 0;6     atomic_set(&t->count, 0);7     t->func = func;8     t->data = data;9 }

該函數接收tasklet_struct結構體指針和小任務函數指針,然后對tasklet_struct結構體進行初始化,并將函數指針賦給t->func域。tasklet_init函數在tasklet_hrtimer_init函數中被調用。

3.tasklet調度(這兩個函數分別在include/linux/interrupt.h和kernel/softirq.c文件中)

1 static inline void tasklet_schedule(struct tasklet_struct *t)2 {3     if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))4         __tasklet_schedule(t);5 }
 1 void __tasklet_schedule(struct tasklet_struct *t) 2 { 3     unsigned long flags; 4  5     local_irq_save(flags); 6     t->next = NULL; 7     *__this_cpu_read(tasklet_vec.tail) = t; 8     __this_cpu_write(tasklet_vec.tail, &(t->next)); 9     raise_softirq_irqoff(TASKLET_SOFTIRQ);10     local_irq_restore(flags);11 }12 EXPORT_SYMBOL(__tasklet_schedule);

在__tasklet_schedule函數第7-8行,將struct tasklet_struct類型的tasklet掛到taskeletvec數組中,然后第9行進行軟中斷掩碼置位。之后當軟中斷被執行時,tasklet函數就可以被執行了。

至此,tasklet的初始化就分析完了。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 西乡县| 凤山市| 栖霞市| 保靖县| 自治县| 阳江市| 福鼎市| 涟源市| 蓝田县| 二手房| 荔波县| 拜城县| 云南省| 措勤县| 全南县| 白水县| 海林市| 辉南县| 车致| 延寿县| 定襄县| 二手房| 策勒县| 进贤县| 马山县| 衡南县| 当阳市| 兴宁市| 兴和县| 罗甸县| 达州市| 龙山县| 青田县| 临漳县| 长海县| 温宿县| 南阳市| 金塔县| 磐安县| 凤阳县| 疏附县|