LinuxÇý¶¯ÖÐֹϰ벿µÄÈýÖÖÒªÁì
ʲôÊÇÖÐֹϰ벿
µ±±¬·¢Ò»ÆäÖÐֹʱ£¬»á½øÈëÖÐÖ¹´¦Àí³ÌÐò¡£
µ«ÖÐÖ¹´¦Àí³ÌÐò±ØÐè¿ìËÙ¡¢Òì²½¡¢¼òÆӵĶÔÓ²¼þ×ö³öѸËÙÏìÓ¦²¢Íê³ÉÄÇЩʱ¼äÒªÇóºÜÑÏ¿áµÄ²Ù×÷¡£
Òò´Ë£¬¹ØÓÚÄÇЩÆäËûµÄ¡¢¶Ôʱ¼äÒªÇóÏà¶Ô¿íËɵÄʹÃü£¬¾ÍÓ¦¸ÃÍƺóµ½ÖÐÖ¹±»¼¤»îÒÔºóÔÙÈ¥ÔËÐС£
ÕâÑù£¬ÕûÆäÖÐÖ¹´¦ÀíÁ÷³Ì¾Í±»·ÖΪÁËÁ½¸ö²¿·Ö£º
µÚÒ»¸ö²¿·ÖÊÇÖÐÖ¹´¦Àí³ÌÐò( Éϰ벿)£¬ÄÚºËͨ¹ý¶ÔËüµÄÒì²½Ö´ÐÐÍê³É¶ÔÓ²¼þÖÐÖ¹µÄ¼´Ê±ÏìÓ¦¡£
ÖÐÖ¹´¦ÀíÁ÷³ÌÖеÄÁíÍâÄÇÒ»²¿·Ö£¬ Ï°벿(bottom half)
Ï°벿µÄʹÃüÖ÷ÒªÊÇÖ´ÐÐÓëÖÐÖ¹Ïà¹ØµÄÊÂÇ飬ÕâЩÊÂÇéûÓб»ÖÐֹЧÀͳÌÐò×Ô¼ºÍê³É¡£
Ï°벿²¢²»ÐèÒªÖ¸Ã÷Ò»¸öÈ·ÇÐʱ¼ä£¬Ö»Òª°ÑÕâЩʹÃüÍƳÙÒ»µã£¬ÈÃËüÃÇÔÚϵͳ²»Ì«Ã¦Âµ²¢ÇÒÖÐÖ¹»Ö¸´ºóÖ´ÐоͿÉÒÔÁË¡£
Éϰ벿ºÍÏ°벿µÄÖ÷ÒªÇø±ð£º
Éϰ벿ָµÄÊÇÖÐÖ¹´¦Àí³ÌÐò£¬Ï°벿ÔòÖ¸µÄÊÇһЩËäÈ»ÓëÖÐÖ¹ÓÐÏà¹ØÐÔ¿ÉÊÇ¿ÉÒÔÑÓºóÖ´ÐеÄʹÃü¡£
Éϰ벿ÖÐÖ¹²»¿É±»ÏàͬÀàÐ͵ÄÖÐÖ¹´ò¶Ï£¬¶øÏ°벿ÒÀÈ»¿ÉÒÔ±»ÖÐÖ¹´ò¶Ï¡£
ͨ³£Ï°벿ÔÚÖÐÖ¹´¦Àí³ÌÐòÒ»·µ»Ø¾Í»áÂíÉÏÔËÐС£
Éϰ벿·Ö¼òÆÓ¿ìËÙ£¬Ö´ÐеÄʱ¼äեȡһЩ»òÕßËùÓÐÖÐÖ¹¡£
Ï°벿·ÖÉÔºóÖ´ÐУ¬²¢ÇÒÖ´ÐÐʱ´ú¿ÉÒÔÏìÓ¦ËùÓеÄÖÐÖ¹¡£
LinuxÖУ¬¶ÔÖÐֹϰ벿µÄʵÏÖÖ÷ÒªÓÐÈýÖÖ£º
ÈíÖÐÖ¹
tasklet
ÊÂÇéÐÐÁÐ
softirq
softirq¼´ÈíÖÐÖ¹£¬´úÂëλÓÚkernel/softirq.cÎļþÖУ»
ÿ¸öÈíÖÐÖ¹ÓÉsoftirq_action½á¹¹ÌåÏÖ£º
ÔÚsoftirq.cÖнç˵ÁËÒ»¸öÈíÖÐÖ¹ÏòÁ¿Êý×ésoftirq_vec£º
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; enum { HI_SOFTIRQ=0, /*ÓÃÓÚ¸ßÓÅÏȼ¶µÄtasklet*/ TIMER_SOFTIRQ, /*ÓÃÓÚ׼ʱÆ÷µÄÏ°벿*/ NET_TX_SOFTIRQ, /*ÓÃÓÚÍøÂç²ã·¢°ü*/ NET_RX_SOFTIRQ, /*ÓÃÓÚÍøÂç²ãÊÕ±¨*/ BLOCK_SOFTIRQ, BLOCK_IOPOLL_SOFTIRQ, TASKLET_SOFTIRQ, /*ÓÃÓÚµÍÓÅÏȼ¶µÄtasklet*/ SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS };
µÇ¼ºó¸´ÖÆ
Êý×éµÄ³ÉÔ±ÊýÓÉNR_SOFTIRQS¾öÒ飬ÊÇÒ»¸öö¾Ù³£Á¿¡£
ÐÂÔöÒ»¸öÈíÖÐֹʱ£¬ÐèÒªÔÚÎļþinclude/linux/interrupt.h ÖÐÌí¼ÓÒ»¸öö¾Ù³£Á¿¡£
ÈíÖÐֹʹÓõļ¸¸öÒªµã£º
Ò»¸öÈíÖÐÖ¹²»»áÇÀÕ¼ÁíÍâÒ»¸öÈíÖÐÖ¹¡£
Ωһ¿ÉÒÔÇÀÕ¼ÈíÖÐÖ¹µÄÊÇÖÐÖ¹´¦Àí³ÌÐò¡£
ÆäËûµÄÈíÖÐÖ¹¿ÉÒÔÔÚÆäËû´¦ÀíÆ÷ÉÏͬʱִÐС£
Ïà¹Ø½Ó¿Ú
×¢²áÈíÖÐÖ¹
void open_softirq(int nr, void (*action)(struct softirq_action *))
µÇ¼ºó¸´ÖÆ
¼´×¢²á¶ÔÓ¦ÀàÐ͵Ĵ¦Àíº¯Êýµ½È«¾ÖÊý×ésoftirq_vecÖС£
´¥·¢ÈíÖÐÖ¹
void raise_softirq(unsigned int nr)
µÇ¼ºó¸´ÖÆ
ÏÖʵÉϼ´ÒÔÈíÖÐÖ¹ÀàÐÍnr×÷ΪƫÒÆÁ¿»áÖÃλirq_stat[cpu_id]µÄ³ÉÔ±±äÁ¿__softirq_pending.
__softirq_pending×Ö¶ÎÖеÄÿһ¸öbit£¬¶ÔÓ¦×Åijһ¸öÈíÖÐÖ¹£¬Ä³¸öbit±»ÖÃλ£¬ËµÃ÷ÓÐÏìÓ¦µÄÈíÖÐÖ¹ÆÚ´ý´¦Àí¡£
ÕâÒ²ÊÇͳһÀàÐÍÈíÖÐÖ¹¿ÉÒÔÔÚ¶à¸öcpuÉϲ¢ÐÐÔËÐеĻù´¡Ôµ¹ÊÔÓÉ¡£
ÈíÖÐֹʵÀý
ÒÔÒ»¸ö°´¼üÇý¶¯µÄÖÐÖ¹´¦ÀíΪÀý£¬½«°´¼üÇý¶¯µÄÖÐÖ¹´¦Àí·Ö³ÉÉÏÏÂÁ½²¿·Ö£º
Éϰ벿£º¶ÁÈ¡¼üÖµ£¬´¥·¢ÈíÖÐÖ¹
Ï°벿£º½ÐÐÑÀú³Ì
ÈíÖÐÖ¹µÄ×¢²á£¬ÔÚÇý¶¯µÄÈë¿Úº¯Êý£¬×¢²áÈíÖÐÖ¹£º
Ìí¼ÓµÄö¾Ù³£Á¿£º
¿ÉÒÔ¿´µ½£¬Ê¹ÓÃÈíÖÐÖ¹ÊÇÐèÒªÐÞ¸ÄÄںˣ¬Ìí¼ÓÒ»¸öö¾ÙµÄ£¬ÓÐЩ·±Ëö¡£
ÒÔÊÇ£¬Í¨³£ÎÒÃDz»½¨Òé˽×ÔÔöÌíÈíÖÐÖ¹µÄÊýÄ¿£¬ÈôÊÇÐèҪеÄÈíÖÐÖ¹£¬¾¡¿ÉÄÜ°ÑËüÃÇʵÏÖΪ»ùÓÚÈíÖÐÖ¹µÄtaskletÐÎʽ¡£
tasklet
taskletÊÇʹÓÃÈíÖÐֹʵÏÖµÄÒ»ÖÖÏ°벿»úÖÆ¡£
ÄÇÊÇÓÃÈíÖÐÖ¹ÕÕ¾ÉtaskletºÃÄØ£¿
Ñ¡Ôñ¾¿¾¹ÊÇÓÃÈíÖÐÖ¹ÕÕ¾Étasklet×ÅʵºÜ¼òÆÓ£º
ͨ³£ÄãÓ¦¸ÃÓÃtasklet¡£¾ÍÏñÎÒÃÇÔÚÇ°Ãæ¿´µ½µÄ£¬ÈíÖÐÖ¹×ÊÔ´ÓÐÏÞ£¬Ò²Æ¶À§£¬²¢ÇÒÈíÖÐÖ¹µÄʹÓÃÕßÇüÖ¸¿ÉÊý¡£ËüÖ»ÔÚÄÇЩִÐÐƵÂʺܸߺÍÒ»Á¬ÐÔÒªÇóºÜ¸ßµÄÇéÐÎϲÅÐèÒª¡£
¶ø taskletÈ´ÓиüÆÕ±éµÄÓÃ;¡£´ó´ó¶¼ÇéÐÎÏÂÓÃtaskletЧ¹û¶¼²»´í£¬²¢ÇÒËüÃÇ»¹ºÜÊÇÈÝÒ×ʹÓá£
ÓÉÓÚ taskletÊÇͨ¹ýÈíÖÐֹʵÏֵģ¬ÒÔÊÇËüÃÇ ×Ô¼ºÒ²ÊÇÈíÖÐÖ¹¡£
taskletʹÓÃ
taskletµÄʹÓð취ÈçÏ£º
1¡¢±àдtasklet´¦Àíº¯Êý£¨Ï°벿£©
void my_tasklet_fun (unsigned long data)
µÇ¼ºó¸´ÖÆ
2¡¢ÉùÃ÷tasklet
//¾²Ì¬ DECLARE_TASKLET(my_tasklet,my_tasklet_fun,data); //¶¯Ì¬ Struct tasklet_struct xxx; tasklet_init(&xxx,tasklet_handler,dev)
µÇ¼ºó¸´ÖÆ
3¡¢µ÷Àí tasklet
tasklet_schedule(&my_tasklet);
µÇ¼ºó¸´ÖÆ
¹ÒºÅmy_tasklet, È»ºóÔÊÐíϵͳÔÚºÏÊʵÄʱ¼äµ÷ÀíËü¡£
taskletʵÀý
ÒÔ°´¼üÖÐÖ¹Çý¶¯ÎªÀý£º
ÏÈʹÓÃDECLARE_TASKLET¾²Ì¬ÉùÃ÷Ò»¸ötasklet£¬Ö¸¶¨ÆäÏ°벿º¯ÊýΪbtn_tasklet_func£¬ÔÚÖÐֹЧÀͺ¯Êý£¨Éϰ벿£©»ñÈ¡°´¼üÖµºó£¬Å²ÓÃtasklet_scheduleµ÷Àí¡£
work queue
work queue¼´ÊÂÇéÐÐÁУ¬Ò²ÊÇÖÐֹϰ벿µÄÒ»ÖÖ¡£
Work queue½«Ï°벿ÊÂÇéÍƳٸøÒ»¸öÄÚºËÏß³ÌÈ¥Ö´ÐÐ ¡ª¡ªwork ×ÜÊÇÔËÐÐÓÚÀú³ÌÉÏÏÂÎÄ.
Á½¸öÒªµã£º
ÈôÊÇÍƳٵÄÊÂÇéÐèÒª ˯Ãߣ¬ÔòʹÓÃwork queues¡£²»È»Ê¹ÓÃsoftirq»òtasklets.
Work queuesÊÊÓÃÓÚÐèÒª·ÖÅÉ´ó×ÚµÄÄڴ棬»ñµÃÒ»¸öÐźÅÁ¿£¬»òÕßÖ´ÐÐÛÕ±ÕµÄI/OµÄÇéÐÎ.
ÊÂÇéÐÐÁеÄÏà¹Ø½Ó¿Úº¯Êý£º
ÔÚʹÓÃÉÏ£¬ÊÂÇéÐÐÁÐÓëtaskletÊÇÀàËƵģº
ÒÔÉϾÍÊÇLinuxÇý¶¯ÖÐֹϰ벿µÄÈýÖÖÒªÁìµÄÏêϸÄÚÈÝ£¬¸ü¶àÇë¹Ø×¢±¾ÍøÄÚÆäËüÏà¹ØÎÄÕ£¡