LECTURE 10 ¥¿¥¹¥¯¥ì¥Ã¥È

¡û ¤Ï¤¸¤á¤Ë

LECTURE 9 ´Êñ¤Ê³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é ¤Ç¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤ÎÅÐÏ¿¡¿¼ÂÁõÊýË¡¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Þ¤·¤¿¡£¤½¤ÎºÝ¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤ÇĹ»þ´Ö¤Î½èÍý¤ò¹Ô¤ï¤Ê¤¤Íͤˤ¹¤ë¤³¤È¡¿Ä¹»þ´Ö¤Î½èÍý¤¬É¬Íפʾì¹ç¤Ï³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤«¤é¥¿¥¹¥¯¥ì¥Ã¥È¤È¸Æ¤Ð¤ì¤ëµ¡Ç½¤òµ¯Æ°¤¹¤ë¤³¤È¤È½ñ¤­¤Þ¤·¤¿¡£

¥¿¥¹¥¯¥ì¥Ã¥È¤È¤Ïͽ¤á¥«¡¼¥Í¥ë¤ËÅÐÏ¿¤·¤Æ¤ª¤¯¤³¤È¤Ç¡¢¥«¡¼¥Í¥ë¤Ë;͵¤¬¤¢¤ë»þ¤Ë¤½¤Î¥¿¥¹¥¯¤ò¼Â¹Ô¤·¤Æ¤â¤é¤¦¤¿¤á¤Îµ¡Ç½¤Ç¤¹¡£Â¨ºÂ¤ËÀ©¸æ¤òÊÖ¤µ¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤Íͤʴؿô¤Ë¤ª¤¤¤Æ¡¢¥¿¥¹¥¯¤ÎͽÌó¤ò¹Ô¤¤¼«¿È¤Ï¤¹¤°½ªÎ»¤¹¤ë¤³¤È¤Ç¡¢¤½¤Î¸å¥«¡¼¥Í¥ë¤¬¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤Ç¥¿¥¹¥¯¤ò¼Â¹Ô¤·¤Æ¤¯¤ì¤Þ¤¹¡£

¤³¤³¤Ç¤Ï¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤«¤é¥¿¥¹¥¯¥ì¥Ã¥È¤òͽÌó¤·¤Þ¤¹¤¬¡¢Ê̤˳ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤«¤éµ¯Æ°¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£write Åù¤Ç¥Ç¥Ð¥¤¥¹¤ËÂФ¹¤ë¥³¥Þ¥ó¥Éȯ¹Ô¤òͽÌ󤷤Ƥª¤­¡¢write ¼«¿È¤Ï¤¹¤°½ªÎ»¤¹¤ë¡¢¤È¤¤¤¦»È¤¤Êý¤ò¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£

¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à

LECTURE 8 I/O ¥Ý¡¼¥È¤ÎÀ©¸æ ¤ÇºîÀ®¤·¤¿¼«ºîÅŻҲóÏ©¤ò»È¤Ã¤Æ¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤«¤é¥¿¥¹¥¯¥ì¥Ã¥È¤òµ¯Æ°¤¹¤ë¥µ¥ó¥×¥ë¥×¥í¥°¥é¥àtasklet.c ¤Ç¤¹¡£¤Ï¤¸¤á¤Ë ¤Î¥Ú¡¼¥¸¤«¤é¡¢Á´¤Æ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ò ¸Ç¤á¤¿ tar ¥Ü¡¼¥ë¤ò¥À¥¦¥ó¥í¡¼¥É¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£

¥×¥Ã¥·¥å¥Ü¥¿¥ó¤ò²¡¤·¤ÆÎ¥¤·¤¿½Ö´Ö¤Ë³ä¤ê¹þ¤ß¤¬È¯À¸¤·¡¢¥¿¥¹¥¯¥ì¥Ã¥È¤¬µ¯Æ°¤·¤Þ¤¹¡£¤½¤Î¥¿¥¹¥¯¥ì¥Ã¥È¤ÎÃæ¤Ç°ìÈÖ²¼¤Î LED ¤Î¾õÂÖ¤òȿž¤¹¤ë¤³¤È¤Ç¡¢¥×¥Ã¥·¥å¥Ü¥¿¥ó¤ò²¡¤¹Å٤˰ìÈÖ²¼¤Î LED ¤¬ÅÀÅô¡¿¾ÃÅô¤ò·«¤êÊÖ¤·¤Þ¤¹¡£³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤ÇľÀܾõÂÖ¤òÀßÄꤷ¤Æ¤¤¤¿¤Î¤ò¡¢¥¿¥¹¥¯¥ì¥Ã¥È¤Ç¹Ô¤¦Íͤˤ·¤¿ÅÀ¤¬°Û¤Ê¤ê¤Þ¤¹¡£

¥¿¥¹¥¯¥ì¥Ã¥Èµ¯Æ°»þ¤Ë¤Ï¥«¡¼¥Í¥ë¥í¥°¤Ë

<6>module [tasklet.o] : Tasklet fire-led being executed.

¤ÎÍͤ˽ÐÎϤµ¤ì¤Æ¤¤¤Þ¤¹¡£

--- tasklet.c ---

    1    #include <asm/io.h>          /* outb(), inb() */
    2    #include <linux/interrupt.h> /* tasklet */
    3    #include <linux/ioport.h>    /* check_region(), request_region(), release_region() */
    4    #include <linux/kernel.h>    /* printk() */
    5    #include <linux/module.h>
    6    #include <linux/sched.h>     /* task_struct */
    7    #include <linux/spinlock.h>
    8    
    9    
   10    MODULE_LICENSE( "GPL" );
   11    
   12    
   13    #define IOPORT_BASE     0x378
   14    #define IOPORT_RANGE    3
   15    
   16    #define IOPORT_DATA     ( IOPORT_BASE + 0 )
   17    #define IOPORT_CONTROL  ( IOPORT_BASE + 2 )
   18    
   19    #define IRQ_NUMBER      7
   20    
   21    #define DATA_LED_3      2
   22    #define DATA_PULLUP     3
   23    #define IRQ_ENABLE      4
   24    
   25    
   26    static char* devname  = "tasklet";
   27    static char* msg      = "module [tasklet.o]";
   28    
   29    static unsigned int initial_data;
   30    static unsigned int initial_control;
   31    
   32    static void tasklet_body( unsigned long value );
   33    DECLARE_TASKLET( tasklet_fire_led, tasklet_body, ( unsigned long )NULL );
   34    
   35    static spinlock_t tasklet_spinlock;
   36    
   37    
   38    /*
   39     * ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é
   40     */
   41    static void
   42    tasklet_interrupt( int irq, void* dev_id, struct pt_regs* regs )
   43    {
   44        tasklet_schedule( &tasklet_fire_led );
   45    }
   46    
   47    
   48    /*
   49     * LED ÁàºîÍÑ¥¿¥¹¥¯¥ì¥Ã¥È¼ÂÂÎ
   50     */
   51    void 
   52    tasklet_body( unsigned long value )
   53    {
   54        unsigned long flags;
   55        unsigned int  data;
   56    
   57        printk( KERN_INFO "%s : Tasklet fire-led being executed.\n", msg );
   58    
   59        spin_lock_irqsave( &tasklet_spinlock, flags );
   60    
   61        data  = inb( IOPORT_DATA );
   62        data ^= ( 1 << DATA_LED_3 );
   63        outb( data, IOPORT_DATA );
   64    
   65        spin_unlock_irqrestore( <tasklet_spinlock, flags );
   66    }
   67    
   68    
   69    /*
   70     * ¥â¥¸¥å¡¼¥ë¤Î½é´ü½èÍý
   71     * insmod »þ¤Ë¸Æ¤Ð¤ì¤ë
   72     */
   73    int 
   74    init_module( void )
   75    {
   76        unsigned int data;
   77    
   78        if ( request_region( IOPORT_BASE, IOPORT_RANGE, devname ) == NULL ) {
   79            printk( KERN_INFO "%s : request_region returned NULL\n", msg );
   80            return -EBUSY;
   81        }
   82    
   83    
   84        if ( request_irq( IRQ_NUMBER, tasklet_interrupt, 0, devname, NULL ) ) {
   85            printk( KERN_INFO "%s : request_irq failed\n", msg );
   86            release_region( IOPORT_BASE, IOPORT_RANGE );
   87            return -EBUSY;
   88        }
   89    
   90        spin_lock_init( &tasklet_spinlock );
   91    
   92        initial_data    = inb( IOPORT_DATA );
   93        initial_control = inb( IOPORT_CONTROL );
   94        rmb();
   95    
   96        data = inb( IOPORT_DATA );
   97        data |= ( 1 << DATA_PULLUP );
   98        outb( data, IOPORT_DATA );
   99        mb();
  100    
  101        data = inb( IOPORT_CONTROL );
  102        data |= ( 1 << IRQ_ENABLE );
  103        outb( data, IOPORT_CONTROL );
  104        mb();
  105        
  106        printk( KERN_INFO "%s : loaded  into kernel\n", msg );
  107        return 0;
  108    }
  109    
  110    
  111    /*
  112     * ¥â¥¸¥å¡¼¥ë¤Î²òÊü½èÍý
  113     * ¥â¥¸¥å¡¼¥ë¤Î»²¾È¿ô¤¬ 0 ¤Ç¤¢¤ì¤Ð¡¢rmmod »þ¤Ë¸Æ¤Ð¤ì¤ë
  114     */
  115    void 
  116    cleanup_module( void )
  117    {
  118        free_irq( IRQ_NUMBER, NULL );
  119        tasklet_kill( &tasklet_fire_led );
  120    
  121        outb( initial_control, IOPORT_CONTROL );
  122        outb( initial_data,    IOPORT_DATA    );
  123    
  124        release_region( IOPORT_BASE, IOPORT_RANGE );
  125    
  126        printk( KERN_INFO "%s : removed from kernel\n", msg );
  127    }
  128    
  129    
  130    /* End of tasklet.c */

¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ÎÀâÌÀ

¤Ç¤Ï¡¢¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤¤¤­¤Þ¤¹¡£¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤Î I/O À©¸æ´ØÏ¢¤Ë¤Ä¤¤¤Æ¤Ï LECTURE 9 ´Êñ¤Ê³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é ¤Î irq_io.h ¤ª¤è¤Ó irq_io.c ¤ÎÀâÌÀ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£

  • 1 ¡Á 7 ¹ÔÌÜ

    ɬÍפʥإåÀ¥Õ¥¡¥¤¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ¤¤¤Þ¤¹¡£2 ¹ÔÌܤǤϡ¢ ¥¿¥¹¥¯¥ì¥Ã¥È¤ò»È¤¦¤¿¤á¤ËɬÍפʥإåÀ¥Õ¥¡¥¤¥ë linux/interrupt.h ¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ¤¤¤Þ¤¹¡£

  • 32 ¡Á 33 ¹ÔÌÜ

    32 ¹ÔÌܤΠstatic void tasklet_body( unsigned long value ) ¤Ï¡¢ ¥¿¥¹¥¯¥ì¥Ã¥È¤Î¼Â½èÍý¤ò¹Ô¤¦´Ø¿ô¤Î¥×¥í¥È¥¿¥¤¥×¤Ç¤¹¡£ 33 ¹ÔÌܤǡ¢DECLARE_TASKLET ¤Ë¤è¤Ã¤Æ¥¿¥¹¥¯¥ì¥Ã¥È¤òÀë¸À¤·¤Æ¤¤¤Þ¤¹¡£

    #include <linux/interrupt.h>
    DECLARE_TASKLET( tasklet_name, tasklet_function, data );
    
    

    tasklet_name ¤Ï¥¿¥¹¥¯¥ì¥Ã¥È¤Ë¤Ä¤±¤ë̾¾Î¡¢tasklet_function ¤Ï ¥¿¥¹¥¯¥ì¥Ã¥È¤Î¼Â½èÍý¤ò¹Ô¤¦´Ø¿ô¤Î¥Ý¥¤¥ó¥¿¡¢data ¤Ï tasklet_function ¤ËÅϤµ¤ì¤ë unsigned long Ãͤò»ØÄꤷ¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢tasklet_name ¤ò»È¤Ã¤Æ¥¿¥¹¥¯¥ì¥Ã¥È¤òµ¯Æ°¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£

    ¤Ê¤ª¥¿¥¹¥¯¥ì¥Ã¥È¤ÎÀë¸À¤Ë¤Ï¡¢Àë¸À¤Ï¤¹¤ë¤±¤Éµ¯Æ°¤·¤Æ¤â¼Â¹Ô¤µ¤ì¤Ê¤¤ ̵¸ú¾õÂÖ¤ÇÀë¸À¤¹¤ë DECLARE_TASKLET_DISABLED ¤È¤¤¤¦¥Þ¥¯¥í¤â¤¢¤ê¤Þ¤¹¡£ °ú¿ô¤Ë¤Ä¤¤¤Æ¤Ï¡¢DECLARE_TASKLET ¤ÈƱ¤¸¤Ç¤¹¡£

  • 38 ¡Á 45 ¹ÔÌÜ ( tasklet_interrupt )

    ¥×¥Ã¥·¥å¥Ü¥¿¥ó¥¹¥¤¥Ã¥Á²¡²¼¾õÂÖ¤«¤éÎ¥¤·¤¿ºÝ¤Ë¼Â¹Ô¤µ¤ì¤ë¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤Ç¤¹¡£ ¼«¿È¤Ç¤Ï²¿¤â¤·¤Æ¤ª¤é¤º¡¢44 ¹ÔÌܤΠtasklet_schedule ¤Ë¤è¤Ã¤Æ¥¿¥¹¥¯¥ì¥Ã¥È ¤òͽÌ󤷤Ƥ¤¤Þ¤¹¡£

    #include <linux/interrupt.h>
    void tasklet_schedule( struct tasklet_struct* t );
    
    

    DECLARE_TASKLET ¤Ç»ØÄꤷ¤¿ tasklet_name ¤ò°ú¿ô¤Ë»ØÄꤷ¤Þ¤¹¡£ ¤³¤ì¤Ë¤è¤ê¡¢ÅÐÏ¿¤·¤¿¥¿¥¹¥¯¤¬°Ê¸å°ìÅÙ¤À¤±¼Â¹Ô¤µ¤ì¤ë¤³¤È¤¬Êݾڤµ¤ì¤Þ¤¹¡£ ¤Ê¤ª¡¢¥«¡¼¥Í¥ë¤Ë;͵¤¬¤¢¤ë»þ´ÖÂӤ˼¹Ԥµ¤ì¤ë¤¿¤á¡¢³Î¼Â¤Ë²¿»þ¼Â¹Ô¤µ¤ì¤ë¤« ÌÀ¸À¤¹¤ë¤³¤È¤Ï¤Ç¤­¤Þ¤»¤ó¡£¤Ê¤ª¡¢¥¿¥¹¥¯¥ì¥Ã¥È¼Â½èÍý¤Î¼Â¹Ô¤Ï¡¢ ¥¿¥¹¥¯¥ì¥Ã¥È¤òͽÌó¤·¤¿ CPU ¾å¤Ç¹Ô¤ï¤ì¤ë¤³¤È¤¬Êݾڤµ¤ì¤Þ¤¹¡£

    ¤Ê¤ª¡¢¥¿¥¹¥¯¥ì¥Ã¥È¤Ë¤ÏÍ­¸ú¡¿Ìµ¸ú¾õÂÖ¤¬Â¸ºß¤·¡¢linux/interrupt.h ¤Ç¥×¥í¥È¥¿¥¤¥×¤¬Àë¸À¤µ¤ì¤Æ¤¤¤ë°Ê²¼¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¾õÂÖ¤òÀÚÂؤ¨¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£

    ´Ø¿ô̾ ÀâÌÀ
    void tasklet_disable( struct tasklet_struct* t ); »ØÄꤷ¤¿¥¿¥¹¥¯¥ì¥Ã¥È¤ò̵¸ú¾õÂ֤ˤ¹¤ë¡£¤³¤ì¤Ë¤è¤ê¡¢tasklet_schedule ¤Ç¤ÎͽÌó¤Ç¤Ï¤Ç¤­¤ë¤¬¡¢Í­¸ú¾õÂ֤ˤʤë¤Þ¤Ç¼Â¹Ô¤µ¤ì¤Ê¤¤¡£
    void tasklet_enable( struct tasklet_struct* t ); »ØÄꤵ¤ì¤¿¥¿¥¹¥¯¥ì¥Ã¥È¤òÍ­¸ú¾õÂ֤ˤ¹¤ë¡£

  • 48 ¡Á 66 ¹ÔÌÜ ( tasklet_body )

    ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤«¤éͽÌ󤵤ì¤ë¥¿¥¹¥¯¥ì¥Ã¥È¤Î¼Â½èÍýÉô¤Ç¤¹¡£ ÅŻҲóÏ©¾å¤Î°ìÈÖ²¼¤Î LED ¤Î¾õÂÖ¤òȿž¤·¤Æ¤¤¤Þ¤¹¡£ ¤è¤Ã¤Æ¡¢¥×¥Ã¥·¥å¥Ü¥¿¥ó¤¬²¡²¼¤µ¤ì¤¿¾õÂÖ¤«¤éÎ¥¤¹Å٤˰ìÈÖ²¼¤Î LED ¤¬ÅÀÅô¡¿¾ÃÅô¤ò·«¤êÊÖ¤·¤Þ¤¹¡£

    ¤Ê¤ª spin_lock_irqsave / spin_unlock_irqrestore ¤Ç¥¹¥Ô¥ó¥í¥Ã¥¯ ¤ò¼èÆÀ¤·¤¿¾õÂÖ¤Ç LED ¤ÎÁàºî¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¤¬¡¢¥¿¥¹¥¯¥ì¥Ã¥È½èÍýÃæ¤ËÊ̤ΠCPU ¤Ë¤ª¤¤¤Æ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é·Ðͳ¤Ç¥¿¥¹¥¯¥ì¥Ã¥È¤¬¼Â¹Ô¤µ¤ì¤ë²ÄǽÀ­¤¬¤¢¤ë¤¿¤á¡¢ ¥¹¥Ô¥ó¥í¥Ã¥¯¤Ë¤è¤Ã¤ÆÇÓ¾½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£³ä¤ê¹þ¤ß¤ò»ß¤á¤ëɬÍפÏÊ̤ˤʤ¤¤Î¤Ç¡¢ ÉáÄ̤Πspin_lock / spin_unlock ¤Ç¤¤¤¤¤È»×¤¤¤Þ¤¹¡£¡£¡£

  • 111 ¡Á 127 ¹ÔÌÜ ( cleanup_module )

    119 ¹ÔÌܤǡ¢tasklet_kill ¤Ë¤è¤êͽÌóºÑ¤ß¤Î¥¿¥¹¥¯¥ì¥Ã¥È¤¬½ªÎ»¤¹¤ë¤Î¤ò ÂÔ¤Á¹ç¤ï¤»¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢¥«¡¼¥Í¥ë¥â¥¸¥å¡¼¥ëºï½ü¸å¤Ë¥«¡¼¥Í¥ë ¤¬¥¿¥¹¥¯¥ì¥Ã¥È¤ò¼Â¹Ô¤·¤è¤¦¤È¤·¤Æ¥Ï¥ó¥°¥¢¥Ã¥×¤¹¤ë¤³¤È¤òËɤ¤¤Ç¤¤¤Þ¤¹¡£

    #include <linux/interrupt.h>
    void tasklet_kill( struct tasklet_struct* t );
    
    

    tasklet_kill ¤ò»È¤¦¾ì¹ç¤Ï¡¢°Ê²¼¤ÎÅÀ¤ËÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡£

    • ¥¿¥¹¥¯¥ì¥Ã¥È½èÍýÃæ¤ËºÆÅÙ¥¿¥¹¥¯¥ì¥Ã¥È¤ò tasklet_schedule ¤Ë¤è¤Ã¤ÆͽÌ󤷤Ƥ¤¤ë¾ì¹ç¡¢ Ää»ß¥Õ¥é¥°Åù¤ÇºÆͽÌ󤷤ʤ¤Íͤˤ·¤¿¾å¤Ç tasklet_kill ¤ò¼Â¹Ô¤·¤Æ¤¯¤À¤µ¤¤ ( ¥«¡¼¥Í¥ë¥¿¥¤¥Þ¡¼¤ò»È¤¦ ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤Ë¤ª¤±¤ë timerstop ¤ÎÍͤʥե饰¤ò»È¤¦ )¡£¤Ç¤Ê¤±¤ì¤Ð¡¢tasklet_kill ¤¬±Ê±ó¤ËÌá¤Ã¤ÆÍè¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹¡£

    • ¥¿¥¹¥¯¥ì¥Ã¥È¤¬Í½Ì󤵤ì¤Æ¤¤¤Æ¤«¤Ä̵¸ú¤Ë¤Ê¤Ã¤Æ¤¤¤ë¾õÂÖ¤Ç tasklet_kill ¤ò¼Â¹Ô¤·¤Ê¤¤¤Ç¤¯¤À¤µ¤¤¡£tasklet_kill ¤Ï¡¢Í½Ì󤵤ì¤Æ¤¤¤ë¥¿¥¹¥¯¥ì¥Ã¥È ¤¬¼Â¹Ô¤µ¤ì¤ë¤Î¤òÂԤäÆÌá¤ê¤Þ¤¹¤¬¡¢Ìµ¸ú¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤È¼Â¹Ô¤µ¤ì¤Ê¤¤¤¿¤á¡¢ ±Ê±ó¤ËÌá¤Ã¤ÆÍè¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹¡£

°Ê¾å¤Ç tasklet.c ¤Î²òÀâ¤Ï½ª¤ï¤ê¤Ç¤¹¡£