Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
$B3d$j9~$_$N8eH>It!"(BSoftirq$B!"(BTasklet$B!"(BWork Queue
[go: Go Back, main page]

$B3d$j9~$_$N8eH>It!"(BSoftirq$B!"(BTasklet$B!"(BWork Queue

					2011$BG/(B02$B7n(B15$BF|(B
$B>pJs2J3XN`(B $B%*%Z%l!<%F%#%s%0%7%9%F%`(B II

                                       $BC^GHBg3X(B $B%7%9%F%`>pJs9)3X8&5f2J(B 
                                       $B%3%s%T%e!<%?%5%$%(%s%9@l96(B, $BEE;R!&>pJs9)3X7O(B
                                       $B?7>k(B $BLw(B
                                       <yas@is.tsukuba.ac.jp>

$B$3$N%Z!<%8$O!" http://www.coins.tsukuba.ac.jp/~yas/coins/os2-2010/2011-02-15
$B$"$k$$$O!" http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/

$B"#:#F|$NBg;v$JOC(B

$B"#3d$j9~$_!"8eH>It(B

$B3d$j9~$_$NLdBjE@(B $B3d$j9~$_%O%s%I%i$O!":9$7Gw$C$?$3$H$@$1$r$7$F!"$=$l0J30$N$3$H$O!"8e$G!"(B $B$+$D!"3d$j9~$_$r5v2D$7$?>uBV$G

$B%G%P%$%9!

$B?^(B? $B3d$j9~$_=hM}$NA0H>ItJ,$H8eH>ItJ,(B

$BA02s!"(B request_irq() $B$G<($7$?$N$O!"A0H>$NOC!#:#F|$O!"8eH>$NOC!#(B

$B"!8eH>It(B(bottom half$B!"(Bbotom halves)

$B8eH>It$N;E;v$O!"3d$j9~$_4XO"$N;E;v$N$&$A!"3d$j9~$_%O%s%I%i$G$O9T$o$J$$(B $BItJ,$r9T$&!#3d$j9~$_%O%s%I%i!JA0H>It!K$r7Z$/$9$k$H!"<+A3$K8eH>It$N;E;v(B $B$OB?$/$J$k!#(B

$B3d$j9~$_%O%s%I%i(B($BA0H>It(B)$B$H8eH>It$NLr3dJ,C4$NL\0B!#(B

Linux $B$G$O!"8eH>It$N;EAH$_$H$7$F!"Nr;KE*;v>p$+$iMM!9$J
  • BH (Botom Half,$B8GM-L>;lE*$J0UL#(B)$B!#:G8E!#%7%9%F%`A4BN(B $B$G(B32 $B8D$N%j%9%H!#%^%k%A%W%m%;%C%5$G$bC` Task Queue$B!#%?%9%/$NCY1d Softirq$B!#F1$8 Tasklet$B!#F1$8e(B $B$K Work Queue$B!#(Btask queue $B$N?7$7$$$b$N!#(B $BIaDL$O!"(BTasklet $B$+(B Work Queue $B$r;H$($P$h$$!#(B

    $BCm0U(B1: Tasklet $B$O!"(Btask $B9=B$BN$H$O$^$C$?$/4X78$J$$!#L>A0$,$h$/$J$$!#(B

    $BCm0U(B2: Softirq $B$H$$$&MQ8l$r!"3d$j9~$_=hM}$N8eH>It$H$$$&0UL#$G;H$&?M$b$$(B $B$k!#(B

    $BCm0U(B3: $BEAE}E*$J(BUnix$B$G$O!"(Btop half $B$O!"%7%9%F%`!&%3!<%k$+$iGI@8$9$k>e0L(B $BAX$N=hM}!"(Bbottom half $B$O!"3d$j9~$_$+$iGI@8$9$k2<0LAX$N=hM}$N0UL#$G;H$o(B $B$l$k$3$H$,$"$k!#(BLinux $B$G$O!"(Btop half, bottom half $B$O!"3d$j9~$_=hM}$NA0(B $BH>ItJ,$H8eH>ItJ,$N0UL#$K;H$&!#(B

    $B"#(BSoftirq

    $B%O!<%I%&%'%"$N(B IRQ $B$H$NBPHf(B

    $B%G%P%$%9!

    $B?^(B? $B%O!<%I%&%'%"$N3d$j9~$_$K$*$1$k%O%s%I%i$N

    $B%G%P%$%9!

    $B?^(B? Softirq$B$G$N%O%s%I%i$N

    $B%O!<%I%&%'%"$N3d$j9~$_(B
    • $B%G%P%$%9$O!"<+J,$N3d$j9~$_?.9f@~$r(B 1 $B$K$9$k!#(B
    • $B3d$j9~$_%3%s%H%m!<%i$O!"(BCPU $B$N3d$j9~$_?.9f@~$r(B 1 $B$K$9$k!#(B
    • CPU $B$O!"E,Ev$J;~(B($B3d$j9~$_6X;_$G$J$$;~(B)$B$K!"3d$j9~$_=hM}$r3+;O$9$k!#(B
    • CPU $B$O!"%P%9$+$i3d$j9~$_%Y%/%?$rFI$_=P$7!"$=$l$,(B n $B$J$i$=$l$KBP1~(B $B$7$?(B IDT (Interrupt Description Table) $B$N%(%s%H%j$r ($B3d$j9~$_A0$N%W%m%0%i%`%+%&%s%?Ey$N>uBV$rJ]B8$7$F(B) $B3d$j9~$_%O%s%I%i$NHVCO$X%8%c%s%W$9$k!#(B
    Softirq
    • $B3d$j9~$_$r5/$3$7$?$$4X?t$O!"(Braise_softirq(n) $B$r8F$S=P$9!#(B
    • raise_softirq() $B$O!"JQ?t(B softirq_pending $B$N(Bn$B%S%C%HL\$r(B 1 $B$K$9$k!#(B
    • Softirq $B$N%7%9%F%`$O!"!VE,Ev$J;~!W$K!"4X?t(B do_softirq() $B$r8F$S=P$9!#(B
    • do_softirq() $B$O!"JQ?t(B softirq_pending $B$N%S%C%H$r=g$KD4$Y$F!"(B n $BHVL\$N%S%C%H$,(B 1 $B$J$i$P(B $BG[Ns(B softirq_vec[n] $B$r;2>H$7$F!"(B Softirq $B$N%O%s%I%i$NHVCO$r do_softirq() $B$O!"(BSoftirq $B$N%O%s%I%i$r8F$S=P$9!#(B
    $B4X?t(B do_softirq() $B$r8F$S=P$9!VE,Ev$J;~!W$H$O!"
  • $B%O!<%I%&%'%"$K$h$k3d$j9~$_%O%s%I%i$N=hM}$,A4$F=*$o$C$F!"3d$j9~$_A0(B $B$N=hM}$KLa$kA0(B
  • ksoftirqd $B%+!<%M%k%9%l%C%I(B $B$,5/>2$7$?;~(B
  • $BL@<(E*$K%A%'%C%/$9$k;~!#%M%C%H%o!<%/=hM}Ey$GMxMQ!#(B

    $B"!(BSoftirq$B$G$ND%$j9~$_%O%s%I%i$NJ];}(B($BG[Ns(B softirq_vec[])

    Softirq$B$N include/linux/interrupt.h struct softirq_action { void (*action)(struct softirq_action *); }; kernel/softirq.c static struct softirq_action softirq_vec[NR_SOFTIRQS];

    $B"!(BSoftirq$B$G$ND%$j9~$_%O%s%I%i(B

    softirq $B$N%O%s%I%i$O!" void softirq_handler(struct softirq_action *a) { ... }
    • Softirq $B$N%O%s%I%i$O!"3d$j9~$_$O5v2D$5$l$?>uBV$GF0$/!#%O!<%I%&%'%"(B $B$N3d$j9~$_$K$h$k3d$j9~$_%O%s%I%i(B($BA0H>It(B)$B$O!"(BSoftirq $B$N%O%s%I%i$N $BJ#?t$N(B Softirq $B$N%O%s%I%i$,J#?t$N(BCPU$B$GF1;~$K 1$B$D$N(B CPU $B$G!"(BSoftirq $B$N%O%s%I%i$O!"B>$N(B Softirq $B$N%O%s%I%i$r3d$j(B $B9~$`$3$H$O$J$$!#(B
    • $B%O!<%I%&%'%"$N3d$j9~$_$K$h$k3d$j9~$_%O%s%I%i(B($BA0H>It(B)$B$O!"(BSoftirq $B$N(B $B%O%s%I%i$N Softirq $B$N%O%s%I%i$O!"(Bsleep $B$G$-$J$$!#(B

    $B"!(Bsoftirq_pending$B$H(Braise_softirq()

    $BJQ?t(Bsoftirq_pending$B$O!"%S%C%H$NG[Ns!#%S%C%H(Bn$B$,(B1$B$J$i$P!"(Bsoftirq_vec[n] $B$r

    $B$3$NJQ?t$N%S%C%H(Bn$B$r(B1$B$K$9$k(B(raise)$B$K$O!" void raise_softirq(unsigned int n) $B$^$:!"3d$j9~$_$,6X;_$7!"(B n $B$G;XDj$5$l$?(B Softirq $B$r $B35G0E*$K$O!" unsigned int softirq_pending; raise_softirq(int n) { softirq_pending |= (1 << n); } $B

  • local_softirq_pending(): $BCM$r set_softirq_pending(x): $BCM$rBeF~$9$k!#(B

    $B"!(Bdo_softirq()

    do_softirq()$B!!$O!"(Braise $B$5$l$?(B Softirq $B$,$"$l$P kernel/softirq.c 55: static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; ... 191: asmlinkage void __do_softirq(void) 192: { ... 194: __u32 pending; ... 198: pending = local_softirq_pending(); ... 207: set_softirq_pending(0); 209: local_irq_enable(); 211: h = softirq_vec; 213: do { 214: if (pending & 1) { ... 219: h->action(h); ... 231: } 232: h++; 233: pending >>= 1; 234: } while (pending); ... 249: }
    • $BJQ?t(B pending $B$O!"(B $BJQ?t(Bsoftirq_pending($B%W%m%;%C%5$4$H$NJQ?t(B)$B$N(B $B4X?tFb$N:n6HMQ$NJQ?t!#%S%C%H$N=89g!#(Bn $B%S%C%HL\$,(B 1 $B$J$i$P!"(Bn $BHVL\$N(B softirq $B$r local_softirq_pending() $B$G!"(B $BJQ?t(Bsoftirq_pending($B%W%m%;%C%5$4$H$NJQ?t(B)$B$r(B $B$BJQ?t(Bsoftirq_pending($B%W%m%;%C%5$4$H$NJQ?t(B)$B$O!"(B set_softirq_pending() $B$G(B0$B$K@_Dj$9$k!#(B
    • local_irq_enable() $B$G%O!<%I%&%'%"$K$h$k3d$j9~$_$r5v2D$9$k!#(B
    • h $B$O!":G=i$OG[Ns(B struct softirq_action softirq_vec[] $B$N@hF,(B(0$BHVL\(B)$B$r(B $B;X$9!#(B
    • pending $B$N1&C<$N%S%C%H$,(B1(pending & 1)$B$J$i!"(B $B$=$N(B softirqs $B$r h $B$r pending $B$r(B 1 $B%S%C%H1&%7%U%H!#(B
    • pending $B$,(B 0 $B$K$J$k$^$G7+$jJV$9!#(B

    $B"!(BSoftirq$B$NMxMQ>l=j(B

    Softirq $B$N include/linux/interrupt.h 376: enum 377: { 378: HI_SOFTIRQ=0, 379: TIMER_SOFTIRQ, 380: NET_TX_SOFTIRQ, 381: NET_RX_SOFTIRQ, 382: BLOCK_SOFTIRQ, 383: BLOCK_IOPOLL_SOFTIRQ, 384: TASKLET_SOFTIRQ, 385: SCHED_SOFTIRQ, 386: HRTIMER_SOFTIRQ, 387: RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ 388: 389: NR_SOFTIRQS 390: }; Softirq $B$Nl=j(B
    • $B%M%C%H%o!<%/=hM}(B
    • $B%V%m%C%/!&%G%P%$%9(B
    • $B%+!<%M%k!&%?%$%^(B
    • Tasklets $B$N $BIaDL$O!"(Btasklets $B$r;H$($P==J,$G!"<+J,$GFH<+$N(B softirqs $B$rDI2C$9$kI,MW$O(B $B$"$^$j$J$$!#?7$7$$(B Softirq $B$rDI2C$7$?$$;~$K$O!"
    • $B>e$N(B enum $B$K%$%s%G%C%/%9$H$J$kDj?t$rDI2C$9$k!#(B
    • Softirq $B%O%s%I%i$H$J$k4X?t$rDj5A$9$k!#(B
    • open_softirq() $B$G!"(BSoftirq $B%O%s%I%i$rEPO?$9$k!#(B
    $B0J2<$O!"%M%C%H%o!<%/=hM}$G$N(B Softirq $B$NMxMQNc!#Aw?.(B(TX, Transmit) $B$H include/linux/interrupt.h 401: struct softirq_action 402: { 403: void (*action)(struct softirq_action *); 404: }; net/core/dev.c 6003: static int __init net_dev_init(void) 6004: { ... 6066: open_softirq(NET_TX_SOFTIRQ, net_tx_action); 6067: open_softirq(NET_RX_SOFTIRQ, net_rx_action); ... 6075: } ... 2557: static void net_tx_action(struct softirq_action *h) 2558: { ... 2612: } ... 3485: static void net_rx_action(struct softirq_action *h) 3486: { ... 3569: }

    $B"!(Bksoftirqd(kernel soft IRQ daemon)

    ksoftirqd $B$O!"(BSoftirq $B$d(B Tasklet $B$r F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND 4 0 1 0 15 0 2160 676 stext Ss ? 0:02 init [5] ... 1 0 3 1 34 19 0 0 ksofti SN ? 0:00 [ksoftirqd/0] ... 1 0 6 1 34 19 0 0 ksofti SN ? 0:00 [ksoftirqd/1] ... $ []

    $BLdBj(B

    • Softirq $B$d(B Tasklet $B$,9bIQEY$G:n$i$l!"$=$l$rM%@h$7$F=hM}$7$?$i!"%f!<(B $B%6%W%m%;%9$,uBV(B)$B!#(B
    • Softirq $B$d(B Tasklet $B$r ksoftirqd $B$O!"$B"#(BTasklet Tasklets $B$O!"(BSoftirqs $B$N>e$K9=C[$5$l$F$$$k!#(B $B$h$j4JC1$J%$%s%?%U%'!<%9$G!"%m%C%/$K4X$9$k@)Ls$,4K$$!#(B

      Tasklet $B$G#1$D$N;E;v$O include/linux/interrupt.h 455: struct tasklet_struct 456: { 457: struct tasklet_struct *next; 458: unsigned long state; 459: atomic_t count; 460: void (*func)(unsigned long); 461: unsigned long data; 462: };

      • func: Tasklet $B%O%s%I%i!#0z?t$O!"(Bdata$B!#(B
      • state: Tasklet $B$N>uBV!#(BTASKLET_STATE_SCHED ($B%9%1%8%e!<%k$5$l$F$$$k!"(B $Be$,$C$F$$$k(B) $B$+(BTASKLET_STATE_RUN ($B count: 0 $B$J$iM-8z!#(B0$B0J30$J$iL58z!#(B $B0l;~E*$KL58z2=$7$?$$$J$i!"(Bcount $B$rA}$d$9!#(B
      • next: $B%j%9%H$r:n$k%]%$%s%?!#(B
      $BA4BN$H$7$F!"

      tasklet_vec$B!

      $B?^(B? Tasklet$B$K$*$1$k;E;v$N%-%e!<(B

      $B"!(BTasklet$B$N9=B$BN$N@k8@(B

      $B@EE*$K(B struct tasklet_struct $B$r@k8@$9$k$K$O!" DECLARE_TASKLET(name, func, data) $BM-8z$J(B(count==0) $B$N(B struct tasklet_struct $B$r@k8@$9$k(B DECLARE_TASKLET_DISABLED(name, func, data) $BL58z$J(B(count==1) $B$N(B struct tasklet_struct $B$r@k8@$9$k(B
      • name: struct tasklet $B9=B$BN$NJQ?tL>(B
      • func: $B%O%s%I%i$H$J$k4X?t(B
      • data: $B%O%s%I%i$KEO$9%G!<%?(B
      kmalloc()$BEy$GF0E*$K3NJ]$7$?>l9g$K$O!" void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); $B$=$NB>$K!"@8@.>CLGM-8zL58z$K4X$7$F
    • tasklet_disable(): $BL58z2=$9$k!J%-%e!<$K$"$k$,$"$k$, tasklet_disable_nosync(): $BL58z2=$7!" tasklet_enable(): $BM-8z$K$9$k(B
    • tasklet_kill(): $B$G%-%e!<$+$i:o=|$9$k(B

    $B"!(BTasklet$B$N%O%s%I%i(B

    Tasklet $B$N%O%s%I%i$O!" void tasklet_handler(unsigned long data) { .... }
    • Tasklet $B$N%O%s%I%i$O!"3d$j9~$_$O5v2D$5$l$?>uBV$GF0$/!#%O!<%I%&%'%"(B $B$N3d$j9~$_$K$h$k3d$j9~$_%O%s%I%i(B($BA0H>It(B)$B$O!"(BTasklet $B$N%O%s%I%i$N $B0[$J$k(B Tasklet $B$O!"J#?t$N(B CPU $B$GF1;~$K $BF1$8(B Tasklet $B$O!"(B1$BEY$K(B1$B$D$7$+F0$+$J$$!#(B
    • Tasklet $B$N%O%s%I%i$O!"(Bsleep $B$G$-$J$$!#(B

    $B"!(BTasklet$B$N

    Tasklet $B$N%O%s%I%i$r void tasklet_schedule(struct tasklet_struct *t) Tasklet t $B$rDL>o$NM%@hEY$G%9%1%8%e!<%k$9$k(B void tasklet_hi_schedule(struct tasklet_struct *t) Tasklet t $B$r9bM%@hEY$G%9%1%8%e!<%k$9$k(B $B$9$k$H!"$=$l$O!V$=$N$&$A$K!W(B1$BEY$@$1$B"!(BTasklet$B$N $B%9%1%8%e!<%k$5$l$?(B Tasklet $B$O!"(Bstruct tasklet_struct $B$GI=8=$5$l!"%W%m%;%C(B $B%5$4$H$N%-%e!<$K$D$J$2$i$k!#(B
    kernel/softirq.c
     351:	struct tasklet_head
     352:	{
     353:	        struct tasklet_struct *head;
     354:	        struct tasklet_struct **tail;
     355:	};
     356:	
     357: static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
     358: static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
    
    • tasklet_vec: $BDL>o$N$b$N(B
    • tasklet_hi_vec: $B9bM%@hEY$N$b$N(B
    include/linux/interrupt.h
     501: static inline void tasklet_schedule(struct tasklet_struct *t)
     502: {
     503:         if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
     504:                 __tasklet_schedule(t);
     505: }
    
    kernel/softirq.c
     360: void __tasklet_schedule(struct tasklet_struct *t)
     361: {
     362:         unsigned long flags;
     363: 
     364:         local_irq_save(flags);
     365:         t->next = NULL;
     366:         *__get_cpu_var(tasklet_vec).tail = t;
     367:         __get_cpu_var(tasklet_vec).tail = &(t->next);
     368:         raise_softirq_irqoff(TASKLET_SOFTIRQ);
     369:         local_irq_restore(flags);
     370: }
    
    • $B>uBV$,(B TASKLET_STATE_SCHED $B$+3NG'$9$k!#$=$&$J$C$F$$$?$i!"(B $B2?$b$7$J$$!#(B
    • __tasklet_schedule() $B$r8F$V!#(B
    • $B3d$j9~$_5v2D!?6X;_$N>uBV$rJ]B8$7!"$=$N%W%m%;%C%5$G$N3d$j9~$_$r6X;_$9$k!#(B $B$3$l$G!"%W%m%;%C%5$4$H$N%G!<%?9=B$$r@jM-$G$-$k!#(B
    • tasklet_vec (tasklet_hi_vec) $B$NKvHx(B(tail) $B$K!"@\B3$9$k!#(B
    • TASKLET_SOFTIRQ $B$N(B Softirq $B$r(B raise $B$9$k!#(B
    • $B3d$j9~$_5v2D!?6X;_$N>uBV$r85$K$b$I$9!#(B

    $B"!(Btasklet_action()

    schedule $B$5$l$?(B Tasklet $B$N%j%9%H$O!"(Btasklet_action() $B$G=g$K kernel/softirq.c 399: static void tasklet_action(struct softirq_action *a) 400: { 401: struct tasklet_struct *list; 402: 403: local_irq_disable(); 404: list = __get_cpu_var(tasklet_vec).head; 405: __get_cpu_var(tasklet_vec).head = NULL; 406: __get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head; 407: local_irq_enable(); 408: 409: while (list) { 410: struct tasklet_struct *t = list; 411: 412: list = list->next; 413: 414: if (tasklet_trylock(t)) { 415: if (!atomic_read(&t->count)) { 416: if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) 417: BUG(); 418: t->func(t->data); 419: tasklet_unlock(t); 420: continue; 421: } 422: tasklet_unlock(t); 423: } 424: 425: local_irq_disable(); 426: t->next = NULL; 427: *__get_cpu_var(tasklet_vec).tail = t; 428: __get_cpu_var(tasklet_vec).tail = &(t->next); 429: __raise_softirq_irqoff(TASKLET_SOFTIRQ); 430: local_irq_enable(); 431: } 432: }
    • $B3d$j9~$_$r6X;_$9$k!#!J3d$j9~$_5v2D!?6X;_$N>uBV$NJ]B8$O!"(BSoftirq $B$N(B $B%O%s%I%i$NCJ3,$G$5$l$F$$$k!#!K(B
    • tasklet_vec $B$N%j%9%H$r(B head $B$+$i$?$I$k!#(B tasklet_vec$B!!<+?H$O!"6u$K$9$k!#(B
    • $B3d$j9~$_$r5v2D$9$k!#(B($B0J8e!"3d$j9~$_%O%s%I%iEy$+$i list $B$NKvHx$^$G(B list = list->next $B$G%k!<%W(B
    • count $B$,(B 0 $B$G$J$$$+$b3NG'$9$k(B
    • state $B$,(B TASKLET_STATE_SCHED $B$+3NG'$7$F!"$5$i$K(BTASKLET_STATE_RUN $B$K$9$k!#(B
    • Tasklet $B$N%O%s%I%i$r8F$S=P$9(B(t->func(t->data))$B!#(B continue $B$G!" tasklet_trylock() $B$G%m%C%/$,$9!#(B

    $B"!(BTasklet$B$NMxMQNc(B

    Atheros Communications Inc$B$NL5@~(BLAN$B$N%I%i%$%P$G$NMxMQNc!#(B
    drivers/net/wireless/ath/ath9k/init.c
     565:         tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
    
    drivers/net/wireless/ath/ath9k/main.c
     623: irqreturn_t ath_isr(int irq, void *dev)
     624: {
    ...
     738:                 tasklet_schedule(&sc->intr_tq);
    ...
     741:         return IRQ_HANDLED;
     744: }
    
     559: void ath9k_tasklet(unsigned long data)
     560: {
    ...
     621: }
    
    • $B=i4|2=;~$K!"(Btasklet_init() $B$G9=B$BN$r=i4|2=$7$F$$$k!#(B
    • $B%O!<%I%&%'%"$N3d$j9~$_%O%s%I%i(B ath_isr() $B$G(B tasklet_schedule() $B$r(B $B8F$s$G$$$k!#(B
    • $B$=$N$&$A$K!"(Bath9k_tasklet() $B$,8F$P$l$k!#(B

    $B"#(BWork Queue

    $B3d$j9~$_$K4XO"$7$?=hM}$G!"l9g(B(Tasklet$B$d(BSoftirq $B$G$OIT2DG=$J(B $B>l9g(B)$B$K(BWork Queue$B;H$&!#(B
    • sleep $B$9$kI,MW$,$"$k!#(B
    • $B3d$j9~$_%3%s%F%-%9%H$G$O$J$/!"%W%m%;%9%3%s%F%-%9%H$G4X?t$r8F$S=P$7$?$$(B
    • $B%a%b%j$r3NJ]$7$?$$(B($B%Z!<%8%"%&%H$N$?$a$K(Bsleep$B$9$k2DG=@-$,$"$k(B)
    • $B%;%^%U%)Ey$NF14|=hM}$r9T$&(B
    ***

    $B"!(BWork Queue$B$N%o!<%+!&%9%l%C%I(B

    Work Queue $B$N%o!<%+!&%9%l%C%I$O!"%+!<%M%k!&%l%Y%k$N%9%l%C%I$G!"(B $B3d$j9~$_=hM}$N8eH>ItJ,$N=hM}$r9T$&$3$H$,$G$-$k!#(B

    workqueue_struct$B!

    $B?^(B? Work Queue$B$K$*$1$k;E;v$N%-%e!<(B

    $B%-%e!<$K$D$J$,$l$k;E;v$O!"(BTasklet $B$N;E;v$H$[$H$s$IF1$8$G!"4X?t$X$N%]%$(B $B%s%?(B func $B$H(B data $B$+$i$J$k!#=hM}$N

    Work Queue $B%G%U%)%k%H$N%o!<%+!&%9%l%C%I$O!"(Bevents/n (n$B$O%W%m%;%C%5HV9f(B) $B$H$h$P$l!"%W%m%;%C%5$4$H$K:n$i$l$k!##1$D$N%9%l%C%I$G!"MM!9$JMW5a85$N;E(B $B;v$r$3$J$9!#(B $BFH<+$N%o!<%+!&%9%l%C%I$r:n$k$3$H$b$G$-$k!#(B

    F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
    4     0     1     0  15   0   2160   676 stext  Ss   ?          0:02 init [5]
    ...
    1     0     8     1  10  -5      0     0 worker S<   ?          0:00 [events/0]
    1     0     9     1  10  -5      0     0 worker S<   ?          0:00 [events/1]
    ...
    $ []
    

    $B"!(Bwork_struct$B9=B$BN(B

    $B%o!<%/!&%-%e!<$GMQ$$$k(B 1 $B$D$N;E;v$O!"9=B$BN(B struct work_struct $B$GI=8=$5(B $B$l$k!#(B
    include/linux/workqueue.h
      18: typedef void (*work_func_t)(struct work_struct *work);
    ...
      79: struct work_struct {
      80:         atomic_long_t data;
      81:         struct list_head entry;
      82:         work_func_t func;
    ...
      86: };
    
    • entry: $B%-%e! func: $B%O%s%I%i(B
    $B struct work_struct my_work; ... INIT_WORK(&my_work,my_work_handler);

    $B"!(BWork Queue $B%O%s%I%i(B

    Work Queue $B%O%s%I%i$O!" void my_work_handler(struct work_struct *work) { ... }

    $B"!(BWork $B$N

    $B%O%s%I%i$r8F$S=P$7$?$$;~$K$O!" schedule_work(&work); $B$3$N7k2L!"(BINIT_WORK() $B$G@_Dj$7$?%O%s%I%i$,%o!<%+!&%9%l%C%I$K$h$j!V$=$N(B $B$&$A!W$K8F$S=P$5$l$k!#(B

    schedule_work() $B$G$O!"B(:B$K/$78e$K schedule_delayed_work(&work,ticks); ticks $B$O!"$I$N$/$i$$4V$r$H$k$+!#C10L$O!"(Bjiffies ($B:#8e$Ne$2$k(B)$B!#(B $BB?$/$N%7%9%F%`$G(B10$B%_%jIC(B-1$B%_%jIC$G!"@_Dj$K$h$C$F0[$J$k!#(B

    $B"!(Bflush_scheduled_work()

    schedule_work() $B$GMW5a$7$?;E;v$,40N;$7$?$3$H$rBT$C$F!"$B"!(Bcreate_workqueue() $BFH<+$N%o!<%+!&%9%l%C%I$H%-%e!<$r:n$j$?$$;~$K$O!" struct workqueue_struct *create_workqueue(char *name) $B%o!<%+!&%9%l%C%I$H%-%e!<$r:n@.$7!"(Bstruct workqueue_struct $B$X$N%](B $B%$%s%?$rJV$9!#0z?t$O!"%o!<%+!&%9%l%C%I$NL>A0!#(B int queue_work(struct workqueue_struct *queue, struct work_struct *work) $B%-%e!<$K;E;v$r2C$($k!#(B int queue_delayed_work(struct workqueue_struct *queue, struct work_struct *work, unsigned long delay) $B%-%e!<$K;E;v$r2C$($k!#$?$@$7!"(Bdelay $B$@$18e$K

    $B"#3d$j9~$_$N8eH>It$NA*Br(B

    • sleep $B$9$kI,MW$,$"$k!J2DG=@-$,$"$k!K$J$i!"(BWork Queue$B!#;H$$J}$b4JC1!#(B
    • $B$=$NB>$N>l9g$O!"(BTasklet$B!#F1$8(B Tasklet $B$O!"(B1$BEY$K(B1$B$D$7$+F0$+$J$$!#(B
    • $B$,$s$P$C$FJBNs@-$r=P$7$?$$$J$i!"(BSoftirq

    $B"#%/%$%:(B8 $B3d$j9~$_$N8eH>It!"(BSoftirq$B!"(BTasklet$B!"(BWork Queue

    $B!zLdBj(B(801) $B3d$j9~$_8eH>$N=hM}(B

    $B3d$j9~$_=hM}$r!"A0H>(B(top half)$B$H8eH>(B(bottom half)$B$KJ,$1$kM}M3$r4JC1$K@b(B $BL@$7$J$5$$!#(B

    $B!zLdBj(B(802) Tasklet$B$N=i4|2=(B

    $B$G8F$S=P$7$?$$!#(B
    void h(void) {
       ....
    }
    
    $B$3$l$r void tasklet_handler(unsigned long data) { /*$B6uMs(B(a)*/ } DECLARE_TASKLET(/*$B6uMs(B(b)*/, /*$B6uMs(B(c)*/, 0); $BCm0U(B: $B9=B$BN$NL>A0$O!"$B!zLdBj(B(803) $B%O%s%I%i$N $BItJ,$N0lIt$G$"$k!#(B $BLdBj(B(802) $B$GDj5A$7$?%O%s%I%i$r8F$V$h$&$K!"6uMs$rKd$a(B $B$J$5$$!#(B
    irqreturn_t irq_handler(int irq, void *dev) {
        /*$B6uMs(B(d)*/
        return IRQ_HANDLED;
    }
    

    Last updated: 2011/02/15 11:50:45
    Yasushi Shinjo / <yas@is.tsukuba.ac.jp>