|
¡û ¤Ï¤¸¤á¤Ë
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 ¤Î²òÀâ¤Ï½ª¤ï¤ê¤Ç¤¹¡£