黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

linux下面的中斷處理軟件中斷tasklet機(jī)制

系統(tǒng) 2563 0

參考:

《Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)》

http://blog.csdn.net/fontlose/article/details/8279113

http://blog.chinaunix.net/uid-27212029-id-3386692.html


tasklet是中斷處理下半部分最經(jīng)常使用的一種方法,驅(qū)動程序一般先申請中斷,在中斷處理函數(shù)內(nèi)完畢中斷上半部分的工作后調(diào)用tasklet。tasklet有例如以下特點(diǎn):


1.tasklet僅僅能夠在一個CPU上同步地運(yùn)行,不同的tasklet能夠在不同地CPU上同步地運(yùn)行。
2.tasklet的實(shí)現(xiàn)是建立在兩個軟件中斷的基礎(chǔ)之上的,即HI_SOFTIRQ和TASKLET_SOFTIRQ,本質(zhì)上沒有什么差別,僅僅只是HI_SOFTIRQ的優(yōu)先級更高一些
3.因?yàn)閠asklet是在軟中斷上實(shí)現(xiàn)的,所以像軟中斷一樣不能睡眠、不能堵塞,處理函數(shù)內(nèi)不能含有導(dǎo)致睡眠的動作,如降低信號量、從用戶空間拷貝數(shù)據(jù)或手工分配內(nèi)存等。
4.一個 tasklet 可以被禁止而且之后被又一次使能; 它不會運(yùn)行直到它被使能的次數(shù)與被禁止的次數(shù)同樣.
5.tasklet的串行化使tasklet函數(shù)不必是可重入的,因此簡化了設(shè)備驅(qū)動程序開發(fā)人員的工作。

6.每一個cpu擁有一個tasklet_vec鏈表,詳細(xì)是哪個cpu的tasklet_vec鏈表,是依據(jù)當(dāng)前線程是執(zhí)行在哪個cpu來決定的。


tasklet是驅(qū)動程序?qū)崿F(xiàn)可延遲函數(shù)的首選方法,tasklet建立在HI_SOFTIRT和TASKLET_SOFTIRQ兩個軟中斷上。
原理
tasklet和高優(yōu)先級的tasklet分別存放在tasklet_vec和tasklet_hi_vec數(shù)組中,二者都包括類型為tasklet_head的
NR_CPUS個元素,每一個元素都是指向tasklet描寫敘述符鏈表的指針。
運(yùn)行過程
HI_SOFTIRQ軟中斷相關(guān)的軟中斷函數(shù)是tasklet_hi_action(),而與TASKLET_SOFTIRQ相關(guān)的函數(shù)是tasklet_action()
? ? ?1.禁止本地中斷
? ? ?2.獲得本地CPU的邏輯號n
? ? ?3.把tasklet_vec[n]或tasklet_hi_vec[n]所指向的鏈表的地址存入局部變量list
? ? ?4.把tasklet_vec[n]或tasklet_hi_vec[n]的值賦為NULL,因此已調(diào)度的tasklet描寫敘述符鏈表被清空
? ? ?5.打開本地中斷
? ? ?6.對于list所指向的每一個tasklet描寫敘述符
? ? ? ? ? ? a.在多處理器系統(tǒng)上,檢查tasklet的TASKLET_STATE_RUN標(biāo)志。
? ? ? ? ? ? ? ? ? ? if標(biāo)志被設(shè)置,list又一次插入結(jié)構(gòu)數(shù)組,并激活TASKLET_SOFTIRQ或HI_SOFTIRQ軟中斷,這個tasklet
? ? 被延遲
? ? ? ? ? ? ? ? ? ? else 設(shè)置TASKLET_STATE_RUN標(biāo)志,以便tasklet不能在其它CPU上執(zhí)行 ? ? ? ? ? ?
? ? ? ? ? ? b.通過查看tasklet描寫敘述符的count字段,看tasklet是否被禁止。假設(shè)是清TASKLET_STATE_RUN標(biāo)志,把
? ? list又一次插入結(jié)構(gòu)數(shù)組,并激活對應(yīng)的軟中斷。
? ? ? ? ? ? c.假設(shè)tasklet被激活,清TASKLET_STATE_SCHED標(biāo)志,并運(yùn)行tasklet函數(shù)
編寫一個設(shè)備驅(qū)動程序的步驟
1.分配一個新的tasklet_struct數(shù)據(jù)結(jié)構(gòu),并用tasklet_init()初始化它;
2.實(shí)現(xiàn)tasklet函數(shù)
3.禁止或使能tasklet

tasklet結(jié)構(gòu)體

  1. struct ?tasklet_struct??
  2. {??
  3. ???? struct ?tasklet_struct?*next;??
  4. ????unsigned? long ?state;??
  5. ????atomic_t?count;??
  6. ???? void ?(*func)(unsigned? long );??
  7. ????unsigned? long ?data;??
  8. };??
  9. ??
  10. tasklet結(jié)構(gòu)變量是tasklet_vec鏈表的一個節(jié)點(diǎn),next是鏈表的下一節(jié)點(diǎn),state使用了兩個位例如以下??
  11. enum ??
  12. {??
  13. ????TASKLET_STATE_SCHED,???? /*?1已經(jīng)被調(diào)度,0表示還沒調(diào)度*/ ??
  14. ????TASKLET_STATE_RUN??? /*?1tasklet正在運(yùn)行,0表示尚未運(yùn)行,僅僅針對SMP有效,單處理器無意義?*/ ??
  15. };??
  16. ??
  17. count用于禁止使能,每禁止一次計(jì)數(shù)加一,沒使能一次計(jì)數(shù)減一,僅僅有禁止次數(shù)和使能次數(shù)一樣(count等于0)時tasklet才會運(yùn)行調(diào)用函數(shù)。??
  18. func?運(yùn)行函數(shù)不能有導(dǎo)致睡眠、不能堵塞的代碼。??
  19. data?運(yùn)行函數(shù)的參數(shù)??


tasklet的定義

  1. 定義時初始化?????
  2. ????定義變量名為name的tasklets_struct變量,并初始化調(diào)用函數(shù)為func,參數(shù)為data,使能tasklet??
  3. ????DECLARE_TASKLET(name,?func,?data);?????#define?DECLARE_TASKLET(name,?func,?data)?\??
  4. ???? struct ?tasklet_struct?name?=?{?NULL,?0,?ATOMIC_INIT(0),?func,?data?}??
  5. ??
  6. ????定義變量名為name的tasklets_struct變量,并初始化調(diào)用函數(shù)為func,參數(shù)為data,禁止tasklet??
  7. ????DECLARE_TASKLET_DISABLED(name,?func,?data);??
  8. ????#define?DECLARE_TASKLET_DISABLED(name,?func,?data)?\ ??
  9. ???? struct ?tasklet_struct?name?=?{?NULL,?0,?ATOMIC_INIT(1),?func,?data?}??
  10. ??
  11. 執(zhí)行中初始化????先定義???? struct ?tasklet_struct?name?;??
  12. ????后初始化????
  13. ??
  14. void ?tasklet_init( struct ?tasklet_struct?*t, void ?(*func)(unsigned? long ),?unsigned? long ?data)??
  15. {??
  16. ????t->next?=?NULL;?????????????? // ??
  17. ????t->state?=?0;???????????????? //設(shè)置為未調(diào)度?未執(zhí)行?? ??
  18. ????atomic_set(&t->count,?0);???? //默認(rèn)使能 ??
  19. ????t->func?=?func;?????????????? //調(diào)用函數(shù) ??
  20. ????t->data?=?data;?????????????? //調(diào)用函數(shù)參數(shù) ??
  21. }??

tasklet的調(diào)用過程

  1. static ? inline ? void ?tasklet_schedule( struct ?tasklet_struct?*t);使用此函數(shù)就可以完畢調(diào)用??
  2. static ? inline ? void ?tasklet_schedule( struct ?tasklet_struct?*t)??
  3. {??
  4. ???? /*test_and_set_bit設(shè)置調(diào)度位TASKLET_STATE_SCHED,test_and_set_bit返回t->state設(shè)置前狀態(tài),假設(shè)設(shè)置前狀態(tài)為1(已被調(diào)用)那么直接退出否則進(jìn)入__tasklet_schedule函數(shù)*/ ??
  5. ???? if ?(!test_and_set_bit(TASKLET_STATE_SCHED,?&t->state))??
  6. ????????__tasklet_schedule(t);??
  7. }??
  8. ??
  9. ??
  10. void ?fastcall?__tasklet_schedule( struct ?tasklet_struct?*t)??
  11. {??
  12. ????unsigned? long ?flags;??
  13. ????local_irq_save(flags);?????????????????????? //關(guān)中斷保存中斷狀態(tài) ??
  14. ????t->next?=?__get_cpu_var(tasklet_vec).list;?? //這兩行用于將新插入的節(jié)點(diǎn)?放置在tasklet_vec鏈表的頭部 ??
  15. ????__get_cpu_var(tasklet_vec).list?=?t;???????? //? ??
  16. ????raise_softirq_irqoff(TASKLET_SOFTIRQ);?????? //觸發(fā)一個軟終端 ??
  17. ????local_irq_restore(flags);??????????????????? //使能中斷的同一時候還恢復(fù)了由?local_irq_save()?所保存的中斷狀態(tài) ??
  18. }??
  19. 至此調(diào)度函數(shù)已經(jīng)觸發(fā)了一個軟中斷,詳細(xì)中斷函數(shù)看tasklet的初始化??
  20. void ?__init?softirq_init( void )??
  21. {??
  22. ????????open_softirq(TASKLET_SOFTIRQ,?tasklet_action,?NULL); //能夠看到軟中斷觸發(fā)后會運(yùn)行tasklet_action這個函數(shù) ??
  23. ????????open_softirq(HI_SOFTIRQ,?tasklet_hi_action,?NULL);??
  24. }??
  25. ??
  26. ??
  27. static ? void ?tasklet_action( struct ?softirq_action?*a)??
  28. {??
  29. ???? struct ?tasklet_struct?*list;??
  30. ??
  31. ????local_irq_disable();??????????????????????? //這里先關(guān)中斷?保證原子操作 ??
  32. ????list?=?__get_cpu_var(tasklet_vec).list;???? //取出tasklet_vec鏈表表頭 ??
  33. ????__get_cpu_var(tasklet_vec).list?=?NULL;???? //由于以下將會一次處理完,這里能夠預(yù)先清空tasklet_vec鏈表,對于為處理完的會又一次增加鏈表 ??
  34. ??????????????????????????????????????????????? //也能夠?qū)嵢缃駎asklet的處理函數(shù)中又一次增加自己。 ??
  35. ????local_irq_enable();??
  36. ??
  37. ??
  38. ??
  39. ???? while ?(list)?{??
  40. ???????? struct ?tasklet_struct?*t?=?list;??????? //取一節(jié)點(diǎn) ??
  41. ??
  42. ????????list?=?list->next;????????????????????? //循環(huán)遍歷所有節(jié)點(diǎn)? ??
  43. ??
  44. ???????? if ?(tasklet_trylock(t))?{?????????????? //這里僅僅是測試TASKLET_STATE_RUN標(biāo)記,防止tasklet反復(fù)調(diào)用?? ??
  45. ??????????????????????????????????????????????? //疑問:這里假設(shè)推斷tasklet已經(jīng)在上執(zhí)行了,trylock失敗,那么為什么后面會被又一次增加鏈表呢,那不是下次又執(zhí)行了? ??
  46. ???????????? if ?(!atomic_read(&t->count))?{????? //疑問:?假設(shè)tasklet被禁止了那么后面有把它加回鏈表中又一次觸發(fā)一次軟中斷,這樣不是一直有軟中斷了嗎?為什么不在禁止的時候移出鏈表,使能時候在增加呢??? ??
  47. ???????????????? if ?(!test_and_clear_bit(TASKLET_STATE_SCHED,?&t->state))? //檢查可調(diào)度位是否設(shè)置了,正常應(yīng)該設(shè)置了的 ??
  48. ?????????????????????BUG();?????????????????????
  49. ????????????????t->func(t->data);?????????????? //處理調(diào)用函數(shù) ??
  50. ????????????????tasklet_unlock(t);????????????? //清TASKLET_STATE_RUN標(biāo)記 ??
  51. ???????????????? continue ;??
  52. ????????????}??
  53. ????????????tasklet_unlock(t);??
  54. ????????}??
  55. ??
  56. ????????local_irq_disable();??
  57. ????????t->next?=?__get_cpu_var(tasklet_vec).list;? //對于trylock失敗和tasklet禁止的節(jié)點(diǎn)會被又一次增加鏈表 ??
  58. ????????__get_cpu_var(tasklet_vec).list?=?t;??
  59. ????????__raise_softirq_irqoff(TASKLET_SOFTIRQ);??? //發(fā)起新的軟中斷,這里有兩條鏈表一條是處理中的鏈表list,一個是當(dāng)前tasklet_vec中的鏈表,當(dāng)出現(xiàn)不能處理的節(jié)點(diǎn)時將節(jié)點(diǎn)又一次增加tasklet_vec中后發(fā)起新的軟中斷,那么未處理的節(jié)點(diǎn)也會在下次中斷中處理。 ??
  60. ????????local_irq_enable();??
  61. ????}??
  62. }??

相關(guān)函數(shù)

  1. /*和tasklet_disable類似,可是tasklet可能仍然執(zhí)行在還有一個?CPU?*/ ??
  2. static ? inline ? void ?tasklet_disable_nosync( struct ?tasklet_struct?*t)??
  3. {??
  4. ????atomic_inc(&t->count);?????? //降低計(jì)數(shù)后,t可能正在執(zhí)行 ??
  5. ????smp_mb__after_atomic_inc();? //保證在多處理器時同步 ??
  6. }??
  7. /*函數(shù)臨時禁止給定的tasklet被tasklet_schedule調(diào)度,直到這個tasklet被再次被enable;若這個tasklet當(dāng)前在執(zhí)行,?這個函數(shù)忙等待直到這個tasklet退出*/ ??
  8. ??
  9. static ? inline ? void ?tasklet_disable( struct ?tasklet_struct?*t){??
  10. ???tasklet_disable_nosync(t);???
  11. ???tasklet_unlock_wait(t);?? //等待TASKLET——STATE_RUN標(biāo)記清零??? ??
  12. ???smp_mb();??
  13. }??
  14. ??
  15. static ? inline ? int ?tasklet_trylock( struct ?tasklet_struct?*t){??
  16. ??? return ?!test_and_set_bit(TASKLET_STATE_RUN,?&(t)->state);??
  17. }??
  18. ??
  19. static ? inline ? void ?tasklet_unlock( struct ?tasklet_struct?*t){?????
  20. ????????smp_mb__before_clear_bit();???????
  21. ????????clear_bit(TASKLET_STATE_RUN,?&(t)->state);??
  22. }??
  23. ??
  24. static ? inline ? void ?tasklet_unlock_wait( struct ?tasklet_struct?*t){??
  25. ???? while ?(test_bit(TASKLET_STATE_RUN,?&(t)->state))?{??
  26. ??????????barrier();???
  27. ?????}??
  28. }??
  29. ??
  30. /*使能一個之前被disable的tasklet;若這個tasklet已經(jīng)被調(diào)度,?它會非常快執(zhí)行。tasklet_enable和tasklet_disable必須匹配調(diào)用,?由于內(nèi)核跟蹤每一個tasklet的"禁止次數(shù)"*/ ???
  31. static ? inline ? void ?tasklet_enable( struct ?tasklet_struct?*t)??
  32. {??
  33. ????smp_mb__before_atomic_dec();??
  34. ????atomic_dec(&t->count);??
  35. }??
  36. ??
  37. /*和tasklet_schedule類似,僅僅是在更高優(yōu)先級執(zhí)行。當(dāng)軟中斷處理執(zhí)行時,?它處理高優(yōu)先級?tasklet?在其它軟中斷之前,僅僅有具有低響應(yīng)周期要求的驅(qū)動才應(yīng)使用這個函數(shù),?可避免其它軟件中斷處理引入的附加周期*/ ??
  38. void ?tasklet_hi_schedule( struct ?tasklet_struct?*t);??
  39. ??
  40. /*確保了?tasklet?不會被再次調(diào)度來執(zhí)行,通常當(dāng)一個設(shè)備正被關(guān)閉或者模塊卸載時被調(diào)用。假設(shè)?tasklet?正在執(zhí)行,?這個函數(shù)等待直到它執(zhí)行完成。若?tasklet?又一次調(diào)度它自己,則必須阻止在調(diào)用?tasklet_kill?前它又一次調(diào)度它自己,如同使用?del_timer_sync*/ ??
  41. void ?tasklet_kill( struct ?tasklet_struct?*t)??
  42. {??
  43. ???? if ?(in_interrupt())??
  44. ????????printk( "Attempt?to?kill?tasklet?from?interrupt\n" );??
  45. ??
  46. ???????? while ?(test_and_set_bit(TASKLET_STATE_SCHED,?&t->state))?{? //檢測t是否被調(diào)度 ??
  47. ???????? do ??
  48. ????????????yield();??
  49. ???????? while ?(test_bit(TASKLET_STATE_SCHED,?&t->state));?????????? //等待t調(diào)度位清零,還未運(yùn)行調(diào)用函數(shù) ??
  50. ????}??
  51. ????tasklet_unlock_wait(t);???????????????????????????????????????? //等待t調(diào)用函數(shù)運(yùn)行完 ??
  52. ????clear_bit(TASKLET_STATE_SCHED,?&t->state);????????????????????? //函數(shù)調(diào)用完可能t被又一次增加鏈表,所以再清一次保證不再調(diào)用 ??
  53. }??
  54. 這個函數(shù)不是真的去殺掉被調(diào)度的tasklet,而是保證tasklet不再調(diào)用 ?

linux下面的中斷處理軟件中斷tasklet機(jī)制


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論