|
¡û ¤Ï¤¸¤á¤Ë
Linux® ( UNIX ) ¤Ç¤Î¥Ç¥Ð¥¤¥¹¤Î·Á¼°¤Ï¡¢Â礤¯°Ê²¼¤Ëʬ¤±¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡£
- ¥¥ã¥é¥¯¥¿¥Ç¥Ð¥¤¥¹
- ¥Ö¥í¥Ã¥¯¥Ç¥Ð¥¤¥¹
- ¥Í¥Ã¥È¥ï¡¼¥¯¥¤¥ó¥¿¡¼¥Õ¥§¡¼¥¹
¥¥ã¥é¥¯¥¿¥Ç¥Ð¥¤¥¹¤È¤Ï¥Ç¡¼¥¿¤ò¥Ð¥¤¥Èñ°Ì¤Ç°·¤¦¥Ç¥Ð¥¤¥¹¤Ç¡¢/dev/ttyS0 ¤ä¥³¥ó¥½¡¼¥ëÅù¤ÏÂåɽŪ¤Ê¥¥ã¥é¥¯¥¿¥Ç¥Ð¥¤¥¹¤Ç¤¹¡£¥Ö¥í¥Ã¥¯¥Ç¥Ð¥¤¥¹¤Ï¥Ç¡¼¥¿¤ò¥Ö¥í¥Ã¥¯¤È¸Æ¤Ð¤ì¤ë°ìÄꥵ¥¤¥º¤Î²ôñ°Ì¤Ç°·¤¦¥Ç¥Ð¥¤¥¹¤Ç¡¢¥Õ¥í¥Ã¥Ô¡¼¥Ç¥£¥¹¥¯¤ä¥Ï¡¼¥É¥Ç¥£¥¹¥¯¤¬ÂåɽŪ¤Ê¥Ö¥í¥Ã¥¯¥Ç¥Ð¥¤¥¹¤Ç¤¹¡£¥Í¥Ã¥È¥ï¡¼¥¯¥¤¥ó¥¿¥Õ¥§¡¼¥¹¤Ï¡¢Ì¾Á°¤ÎÄ̤ê¥Í¥Ã¥È¥ï¡¼¥¯´ØÏ¢¤Î½èÍý¤ò¹Ô¤¦¥Ç¥Ð¥¤¥¹¤Ç¤¹¡£
¤³¤ì¤é°Ê³°¤Ë¤â SCSI Åù¤¤¤í¤¤¤í¤Ê¥Ç¥Ð¥¤¥¹¤¬¤¢¤ê¤Þ¤¹¤¬¡¢¤½¤ì¤é¤Ï¹½Â¤¤¬°Û¤Ê¤ë¤¿¤á¾åµ¤ÎÍͤˤޤȤá¤ë¤³¤È¤¬½ÐÍè¤Ê¤¤ÍͤǤ¹¡£
¤³¤ì¤«¤é¤·¤Ð¤é¤¯¤Ï¡¢Èæ³ÓŪÁ´ÂÎÁü¤¬ÄϤߤ䤹¤¤¥¥ã¥é¥¯¥¿¥Ç¥Ð¥¤¥¹¤òºî¤Ã¤Æ¤¤¤¤¿¤¤¤È»×¤¤¤Þ¤¹¡£
¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à
open / close / read / write ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ËÂбþ¤·¤¿¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à chardev.c ¤Ç¤¹¡£¤Ï¤¸¤á¤Ë ¤Î¥Ú¡¼¥¸¤«¤é¡¢Á´¤Æ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ò ¸Ç¤á¤¿ tar ¥Ü¡¼¥ë¤ò¥À¥¦¥ó¥í¡¼¥É¤¹¤ë¤³¤È¤â¤Ç¤¤Þ¤¹¡£
gcc -DMODULE -D__KERNEL__ -O -c chardev.c
Á°²ó¤È°ã¤¤¡¢__KERNEL__ ¤ò¥³¥ó¥Ñ¥¤¥ë¥ª¥×¥·¥ç¥ó¤È¤·¤Æ»ØÄꤷ¤Æ¤¤¤Þ¤¹¡£¥«¡¼¥Í¥ë¥Ø¥Ã¥À¤ÎÃæ¤Ë¤Ï¡¢¥«¡¼¥Í¥ë¤Ç¤·¤«»²¾È¤·¤Ê¤¤Íͤʥǡ¼¥¿¹½Â¤Åù¤ò__KERNEL__ ¥Þ¥¯¥í¤ÇÊݸ¤Æ¤¤¤Þ¤¹¤¬¡¢¤½¤ì¤é¤Ë¥¢¥¯¥»¥¹¤¹¤ëɬÍפ¬¤¢¤ë¤«¤é¤Ç¤¹¡£¤³¤ì°Ê¹ß¤Î¥µ¥ó¥×¥ë¤Ç¤Ï¡¢É¬¤º»ØÄꤷ¤Þ¤¹¡£¤Ê¤ª¡¢¥½¡¼¥¹Ãæ¤Ëµ½Ò¤¹¤ëºÝ¤Ë¤Ï¤É¤Î¥«¡¼¥Í¥ë¥Ø¥Ã¥À¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¤è¤ê¤âÀè¤ËÄêµÁ¤·¤Æ²¼¤µ¤¤¡£
¤Þ¤¿¡¢ºÇŬ²½¥ª¥×¥·¥ç¥ó -O ¤Ï¥¤¥ó¥é¥¤¥ó´Ø¿ô¤òŸ³«¤¹¤ë¤¿¤á¤Ë»ØÄꤷ¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ï¡¢¥«¡¼¥Í¥ëÆâ¤Î¿¤¯¤Î´Ø¿ô¤¬¥¤¥ó¥é¥¤¥ó´Ø¿ô¤È¤·¤ÆÄêµÁ¤µ¤ì¤Æ¤ª¤ê¡¢ºÇŬ²½¥ª¥×¥·¥ç¥ó¤ò»ØÄꤷ¤Ê¤¤¤È¤½¤ì¤é¤¬Å¸³«¤µ¤ì¤Ê¤¤¤¿¤á¡¢¥³¥ó¥Ñ¥¤¥ë¤Ë¼ºÇÔ¤¹¤ë¤«¤é¤Ç¤¹¡£
chardev.c ¤Ï¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¤Î open / close / read / write ¤ËÂбþ¤·¤Æ¤¤¤Þ¤¹¤¬¡¢¤½¤ì¤¾¤ì¤ò¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¼Â¹Ô¤¹¤ë¤¿¤á¤Ë¥Ç¥Ð¥¤¥¹¥Õ¥¡¥¤¥ë¤òºîÀ®¤·¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡£¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð¤È¥Ç¥Ð¥¤¥¹¥Õ¥¡¥¤¥ë¤Ï¡¢¥á¥¸¥ã¡¼ÈÖ¹æ¤È¥Þ¥¤¥Ê¡¼ÈÖ¹æ¤È¸Æ¤Ð¤ì¤ë¿ôÃͤǷë¤Ó¤Ä¤±¤é¤ì¤Þ¤¹¡Ê¥Ç¥Ð¥¤¥¹¥Õ¥¡¥¤¥ë̾¾Î¤Ï½Å¤Ê¤é¤Ê¤±¤ì¤Ð²¿¤Ç¤âÎɤ¤¡Ë¡£¥á¥¸¥ã¡¼ÈÖ¹æ¤Ç¥«¡¼¥Í¥ë¤¬¥É¥é¥¤¥Ð¤ò¶èÊ̤·¡¢¥Þ¥¤¥Ê¡¼ÈÖ¹æ¤Ç¥É¥é¥¤¥Ð¤¬¥Ç¥Ð¥¤¥¹¤ò¶èÊ̤·¤Þ¤¹¡£chardev.c ¤Ç¤Ï¥Þ¥¤¥Ê¡¼ÈÖ¹æ¤ò»ÈÍѤ·¤Ê¤¤¡ÊƱ¤¸¥É¥é¥¤¥Ð¤ÇÊ£¿ô¤Î¥Ç¥Ð¥¤¥¹¤ò°·¤¦¤ï¤±¤Ç¤Ï¤Ê¤¤¡Ë¤Î¤Ç¡¢¥á¥¸¥ã¡¼ÈÖ¹æ¤Î¤ß¤¬Âç»ö¤Ç¤¹¡£chardev.c ¤Î 13 ¹ÔÌܤǻÈÍѤ¹¤ë¥á¥¸¥ã¡¼ÈÖ¹æ¤ò 77 ¤ÈÄêµÁ¤·¤Æ¤¤¤Þ¤¹¡£¤â¤·¡¢³Æ¼«¤Î¥·¥¹¥Æ¥à¾å¤Ç»ÈÍѺѤߤÎÈÖ¹æ¤Ç¤¢¤ë¾ì¹ç¤Ï¡¢»È¤ï¤ì¤Æ¤¤¤Ê¤¤Ê̤ÎÈÖ¹æ¤ËÃÖ¤´¹¤¨¤Æ²¼¤µ¤¤¡£¤Ê¤ª¡¢¥á¥¸¥ã¡¼ÈÖ¹æ¤ÏưŪ¤Ë³ä¤êÅö¤Æ¤ë¤³¤È¤â¤Ç¤¤Þ¤¹¤¬¡¢¤³¤³¤Ç¤Ï¿¨¤ì¤Þ¤»¤ó¡£
¤³¤³¤Ç¤Ï¥Ç¥Ð¥¤¥¹¥Õ¥¡¥¤¥ë̾ /dev/chardev ¤ò»È¤¦¤³¤È¤Ë¤·¤Þ¤¹¡£¥Þ¥¤¥Ê¡¼ÈÖ¹æ¤Ï²¿¤Ç¤âÎɤ¤¤Î¤Ç 0 ¤Ë¤·¤Þ¤¹¡£°Ê²¼¤ÎÍͤˤ·¤Æ¥Ç¥Ð¥¤¥¹¥Õ¥¡¥¤¥ë¤òºîÀ®¤·¤Æ²¼¤µ¤¤ ( root ¤Ç¹Ô¤Ã¤Æ²¼¤µ¤¤ )¡£
mknod /dev/chardev c 77 0 chmod 0666 /dev/chardev
insmod ¤Ç¥â¥¸¥å¡¼¥ë¤òÁȤ߹þ¤ó¤À¸å¤Ï¡¢
echo "HELLO WORLD" > /dev/chardev
¤ÎÍͤˤ·¤Æ½ñ¤¹þ¤ß¤ò¹Ô¤¤
cat /dev/chardev HELLO WORLD
¤ÎÍͤˤ·¤Æ½ñ¤¹þ¤ó¤ÀÆâÍƤòÆɤ߹þ¤à¤³¤È¤¬½ÐÍè¤Þ¤¹¡£ÄÌ»» 32 ¥Ð¥¤¥È°Ê¾å¤ò½ñ¤¹þ¤â¤¦¤È¤¹¤ë¤È¡¢¥«¡¼¥Í¥ë¥í¥°¤Ë
<6>module [chardev.o] : no space left
¤ÎÍͤËɽ¼¨¤µ¤ì¤Þ¤¹¡£¤Ê¤ª¡¢/dev/chardev ¤Ï¡¢Æ±»þ¤Ë°ì¤Ä¤Î¥æ¡¼¥¶¥×¥í¥»¥¹¤·¤«»ÈÍѤ¹¤ë¤³¤È¤¬¤Ç¤¤Þ¤»¤ó¡£
--- chardev.c ---
1 #include <asm/uaccess.h> /* copy_from_user, copy_to_user */ 2 #include <linux/errno.h> 3 #include <linux/fs.h> /* inode, file, file_operations */ 4 #include <linux/kernel.h> /* printk */ 5 #include <linux/module.h> 6 #include <linux/spinlock.h> 7 8 9 MODULE_AUTHOR( "Ryo" ); 10 MODULE_DESCRIPTION( "Sample character device driver." ); 11 MODULE_LICENSE( "GPL" ); 12 13 14 static int devmajor = 77; 15 static char* devname = "chardev"; 16 static char* msg = "module [chardev.o]"; 17 18 19 #define MAXBUF 32 20 static unsigned char devbuf[ MAXBUF ]; 21 static int buf_pos; 22 23 static int access_num; 24 static spinlock_t chardev_spin_lock; 25 26 27 /* 28 * open() 29 * 1¥æ¡¼¥¶¥×¥í¥»¥¹¤Î¤ß¤¬¥Ç¥Ð¥¤¥¹¥Õ¥¡¥¤¥ë¤Î open ¤ËÀ®¸ù¤¹¤ë¡£ 30 */ 31 static int 32 chardev_open( struct inode* inode, struct file* filp ) 33 { 34 printk( KERN_INFO "%s : open() called\n", msg ); 35 36 spin_lock( &chardev_spin_lock ); 37 38 if ( access_num ) { 39 spin_unlock( &chardev_spin_lock ); 40 return -EBUSY; 41 } 42 43 access_num ++; 44 spin_unlock( &chardev_spin_lock ); 45 46 return 0; 47 } 48 49 50 /* 51 * release() 52 * »ÈÍѥ桼¥¶¥×¥í¥»¥¹¿ô¤ò¥¯¥ê¥¢¤¹¤ë¡£ 53 */ 54 static int 55 chardev_release( struct inode* inode, struct file* filp ) 56 { 57 printk( KERN_INFO "%s : close() called\n", msg ); 58 59 spin_lock( &chardev_spin_lock ); 60 access_num --; 61 spin_unlock( &chardev_spin_lock ); 62 63 return 0; 64 } 65 66 67 /* 68 * read() 69 * ¥æ¡¼¥¶¥×¥í¥»¥¹¤ËÂФ·¤ÆÆâÉô¥Ð¥Ã¥Õ¥¡¤ÎÆâÍƤòžÁ÷¤¹¤ë¡£ 70 * žÁ÷¤·¤¿ÆâÍƤÏÆâÉô¥Ð¥Ã¥Õ¥¡¤«¤é¾Ã¤¨¤ë¡£ 71 */ 72 static ssize_t 73 chardev_read( struct file* filp, char* buf, size_t count, loff_t* pos ) 74 { 75 int copy_len; 76 int i; 77 78 printk( KERN_INFO "%s : read() called\n", msg ); 79 80 if ( count > buf_pos ) 81 copy_len = buf_pos; 82 else 83 copy_len = count; 84 85 if ( copy_to_user( buf, devbuf, copy_len ) ) { 86 printk( KERN_INFO "%s : copy_to_user failed\n", msg ); 87 return -EFAULT; 88 } 89 90 *pos += copy_len; 91 92 for ( i = copy_len; i < buf_pos; i ++ ) 93 devbuf[ i - copy_len ] = devbuf[i]; 94 95 buf_pos -= copy_len; 96 printk( KERN_INFO "%s : buf_pos = %d\n", msg, buf_pos ); 97 98 return copy_len; 99 } 100 101 102 /* 103 * write() 104 * ¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤éžÁ÷¤µ¤ì¤¿ÆâÍƤòÆâÉô¥Ð¥Ã¥Õ¥¡¤Ë½ñ¤¹þ¤à¡£ 105 */ 106 static ssize_t 107 chardev_write( 108 struct file* filp, const char* buf, size_t count, loff_t* pos ) 109 { 110 int copy_len; 111 112 printk( KERN_INFO "%s : write() called\n", msg ); 113 114 if ( buf_pos == MAXBUF ) { 115 printk( KERN_INFO "%s : no space left\n", msg ); 116 return -ENOSPC; 117 } 118 119 if ( count > ( MAXBUF - buf_pos ) ) 120 copy_len = MAXBUF - buf_pos; 121 else 122 copy_len = count; 123 124 if ( copy_from_user( devbuf + buf_pos, buf, copy_len ) ) { 125 printk( KERN_INFO "%s : copy_from_user failed\n", msg ); 126 return -EFAULT; 127 } 128 129 *pos += copy_len; 130 buf_pos += copy_len; 131 132 printk( KERN_INFO "%s : buf_pos = %d\n", msg, buf_pos ); 133 return copy_len; 134 } 135 136 137 static struct file_operations chardev_fops = 138 { 139 owner : THIS_MODULE, 140 read : chardev_read, 141 write : chardev_write, 142 open : chardev_open, 143 release : chardev_release, 144 }; 145 146 147 /* 148 * ¥â¥¸¥å¡¼¥ë¤Î½é´ü½èÍý 149 * insmod »þ¤Ë¸Æ¤Ð¤ì¤ë 150 */ 151 int 152 init_module( void ) 153 { 154 if ( register_chrdev( devmajor, devname, &chardev_fops ) ) { 155 printk( KERN_INFO "%s : register_chrdev failed\n" ); 156 return -EBUSY; 157 } 158 159 spin_lock_init( &chardev_spin_lock ); 160 printk( KERN_INFO "%s : loaded into kernel\n", msg ); 161 162 return 0; 163 } 164 165 166 /* 167 * ¥â¥¸¥å¡¼¥ë¤Î²òÊü½èÍý 168 * ¥â¥¸¥å¡¼¥ë¤Î»²¾È¿ô¤¬ 0 ¤Ç¤¢¤ì¤Ð¡¢rmmod »þ¤Ë¸Æ¤Ð¤ì¤ë 169 */ 170 void 171 cleanup_module( void ) 172 { 173 if ( unregister_chrdev( devmajor, devname ) ) { 174 printk( KERN_INFO "%s : unregister_chrdev failed\n" ); 175 /* Âкö̵¤· ... */ 176 } 177 178 printk( KERN_INFO "%s : removed from kernel\n", msg ); 179 } 180 181 182 /* End of chardev.c */
¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ÎÀâÌÀ
¤Ç¤Ï¡¢¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤¤¤¤Þ¤¹¡£
- 1 ¡Á 6 ¹ÔÌÜ
ɬÍפʥإåÀ¥Õ¥¡¥¤¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤é¤ÎÃæ¤Ë¤Ï¡¢ __KERNEL__ ¥Þ¥¯¥í¤ÇÆâÍƤòÊݸ¤Æ¤¤¤ë²Õ½ê¤¬¤¢¤ê¤Þ¤¹¤Î¤Ç¡¢ÀèƬ¤Ë __KERNEL__ ¤Èµ½Ò¤¹¤ë¤«¥³¥ó¥Ñ¥¤¥ë¥¹¥¤¥Ã¥Á¤ÇÄêµÁ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£
- 9 ¡Á 11 ¹ÔÌÜ
MODULE_AUTHOR ¤È MODULE_DESCRIPTION ¤Ï¡¢¤½¤ì¤¾¤ì¥â¥¸¥å¡¼¥ëºîÀ®¼Ô ¤ª¤è¤Ó¥â¥¸¥å¡¼¥ë¤Ë¤Ä¤¤¤Æ¤ÎÀâÌÀ¤ò¥«¡¼¥Í¥ë¥â¥¸¥å¡¼¥ëÆâ¤ËËä¤á¹þ¤à¤¿¤á¤Î ¥Þ¥¯¥í¤Ç¤¹¡£Æ°ºî¾åɬ¿Ü¤È¤¤¤¦¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£MODULE_LICENSE ¥Þ¥¯¥í¤Ë¤Ä¤¤¤Æ¤Ï¡¢Á°²ó¤ÎÀâÌÀÄ̤ê¤Ç¤¹¡£
- 14 ¹ÔÌÜ
chardev.c ¤Ç»ÈÍѤ¹¤ë¥á¥¸¥ã¡¼ÈÖ¹æ¤ò 77 È֤Ȥ·¤Æ¤¤¤Þ¤¹¡£Â¾¤ÎÈÖ¹æ¤ò »È¤¤¤¿¤¤»þ¤Ë¤Ï¡¢¤³¤³¤ò½ñ¤´¹¤¨¤¿¾å¤ÇƱ¤¸ÈÖ¹æ¤ò»È¤Ã¤Æ mknod ¤Ç¥Ç¥Ð¥¤¥¹ ¥Õ¥¡¥¤¥ë¤òºîÀ®¤·¤Æ²¼¤µ¤¤¡£
- 19 ¡Á 21 ¹ÔÌÜ
¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é½ñ¤¹þ¤Þ¤ì¤¿¥Ç¡¼¥¿¤òÊݸ¤·¡¢¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é Æɤ߹þ¤á¤ëÍͤˤ¹¤ë¤¿¤á¤ÎÆâÉô¥Ð¥Ã¥Õ¥¡ 32 ¥Ð¥¤¥È¤òÀë¸À¤·¤Æ¤¤¤Þ¤¹¡£
- 23 ¡Á 24 ¹ÔÌÜ
Ʊ»þ¥¢¥¯¥»¥¹²Äǽ¥×¥í¥»¥¹¿ô¤ò´ÉÍý¤¹¤ë¤¿¤á¤ÎÊÑ¿ô¤Ç¤¹¡£chardev.c ¤Ç¤Ï¡¢ Ʊ»þ¤Ë 1 ¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¤Î¥¢¥¯¥»¥¹¤·¤«µö²Ä¤·¤Þ¤»¤ó¡£open ¤¬¼Â¹Ô¤µ¤ì¤¿ºÝ¤Ë access_num ¤¬ 0 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤ì°Ê¹ß¤ÎÁàºî¤ò¹Ô¤¨¤Ê¤¤Íͤˤ·¤Æ¤¤¤Þ¤¹¡£ ¤Þ¤¿¡¢SMP ¥·¥¹¥Æ¥àÍÑ¤Ë access_num ¤ÎÁàºî¤òÇÓ¾À©¸æ¤¹¤ë¤¿¤á¤Î¥í¥Ã¥¯ ÊÑ¿ô chardev_spin_lock ¤òÍÑ°Õ¤·¤Æ¤¤¤Þ¤¹¡£¥¹¥Ô¥ó¥í¥Ã¥¯¤Ë¤Ä¤¤¤Æ¤Ï¸å½Ò¤·¤Þ¤¹¡£
- 27 ¡Á 47 ¹ÔÌÜ ( chardev_open )
¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¤Î open ¤ËÂбþ¤¹¤ë´Ø¿ô¤Ç¤¹¡£linux/fs.h Æâ¤Î struct file_operations ¤Î¥á¥ó¥Ð¤Ç¤¢¤ë open ´Ø¿ô¥Ý¥¤¥ó¥¿¤Î·Á¼°¤Ç ÄêµÁ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£À®¸ù»þ¤Ë¤Ï 0 ¤ò¡¢²¿¤é¤«¤Î¥¨¥é¡¼½ªÎ»»þ¤Ë¤Ï linux/errno.h Æâ¤ÎŬÀڤʥ¨¥é¡¼ÈÖ¹æ¤òÁª¤Ó¡¢Éé¤Î¿ôÃͤËÊÑ´¹¤·¤ÆÊֵѤ·¤Þ¤¹¡£ ¤³¤³¤Ç¤Ï¡¢access_num ¤¬ 0 ¤Ç¤Ê¤¤¡Ê´û¤Ë»ÈÍѤµ¤ì¤Æ¤¤¤ë¡Ë¾ì¹ç¤Ë¤Ï EBUSY ¤òÊÖ¤·¤Æ½ªÎ»¤·¤Æ¤¤¤Þ¤¹¡£
access_num ¤ÎÁàºî¤ò¹Ô¤¦Á°¸å¤Ë¡¢spin_lock / spin_unlock ¤È¤¤¤¦½èÍý¤ò¼Â¹Ô¤·¤Æ¤¤¤Þ¤¹¡£SMP ¥·¥¹¥Æ¥à¤Î¾ì¹ç¤Ï¡¢access_num ¤Î 0 ¥Á¥§¥Ã¥¯¤È¼ÂºÝ¤ÎÁýʬ½èÍý¤Î´Ö¤ËÊÌ CPU ¤¬³ä¤ê¹þ¤à²ÄǽÀ¤¬¤¢¤ê¤Þ¤¹¡£ ¤½¤ì¤Ç¤ÏÌäÂ꤬¤¢¤ë¤¿¤á¡¢access_num ¤Î¥Á¥§¥Ã¥¯¤ª¤è¤ÓÁýʬ½èÍý¤ÎÁ°¤Ë ²¿¤é¤«¤Î¥í¥Ã¥¯¤ò¼èÆÀ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£¥í¥Ã¥¯¤Ë¤â¤¤¤í¤¤¤í¤¢¤ê¤Þ¤¹¤¬¡¢ ¤´¤¯Ã»»þ´Ö¤Î´Ö¤À¤±¥í¥Ã¥¯¤Ç¤¤ì¤ÐÎɤ¤Íͤʾì¹ç¤Ë¤Ï¥¹¥Ô¥ó¥í¥Ã¥¯¤ò»È¤¤¤Þ¤¹¡£
#include <linux/spinlock_h> spin_lock_init( spinlock_t* lock ); spin_lock( spinlock_t* lock ); spin_unlock( spinlock_t* lock );
¥¹¥Ô¥ó¥í¥Ã¥¯¤Ï¡¢¥í¥Ã¥¯¤ò¼èÆÀ¤¹¤ë¤Þ¤Ç¥Ó¥¸¡¼¥ë¡¼¥×¤ÇÂÔ¤Á¤Þ¤¹¡£ ¤Ê¤ª¡¢__SMP__ ¤òÄêµÁ¤»¤º¤Ë¥³¥ó¥Ñ¥¤¥ë¤·¤¿¾ì¹ç¡¢ ¥¹¥Ô¥ó¥í¥Ã¥¯¤Ï²¿¤â½èÍý¤·¤Þ¤»¤ó¡£¤Þ¤¿¡¢¥¹¥Ô¥ó¥í¥Ã¥¯¤ò»È¤¦ºÝ¤Ë¤Ï ¤¢¤é¤«¤¸¤á spin_lock_init ¤Ç½é´ü²½¤ò¹Ô¤¦É¬Íפ¬¤¢¤ê¤Þ¤¹¡£chardev.c ¤Ç¤Ï init_module Æâ¤Ç¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
- 50 ¡Á 64 ¹ÔÌÜ ( chardev_release )
¥æ¡¼¥¶¥×¥í¥»¥¹¤È¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð¤Î´ØÏ¢ÉÕ¤±¤¬²òÊü¤µ¤ì¤ëºÝ¤Ë¼Â¹Ô¤µ¤ì¤Þ¤¹¡£ °ìÈÌŪ¤Ë¤Ï¥æ¡¼¥¶¥×¥í¥»¥¹¤¬ close ¤ò¼Â¹Ô¤·¤¿ºÝ¤Ë¼Â¹Ô¤µ¤ì¤Þ¤¹¤¬¡¢ ¥æ¡¼¥¶¥×¥í¥»¥¹¤¬¥¨¥é¡¼½ªÎ»¤·¤Æ¤·¤Þ¤Ã¤¿ºÝ¤Ê¤É¤Ë¤â¼Â¹Ô¤µ¤ì¤ë¤³¤È¤Ç¡¢ »ñ¸»¤¬²òÊü¤µ¤ì¤Þ¤¹¡£linux/fs.h Æâ¤Î struct file_operations ¤Î¥á¥ó¥Ð¤Ç¤¢¤ë release ´Ø¿ô¥Ý¥¤¥ó¥¿¤Î·Á¼°¤ÇÄêµÁ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£ ÊÖµÑÃͤˤĤ¤¤Æ¤Ï chardev_open ¤ÈƱ¤¸¤Ç¤¹¡£¤³¤³¤Ç¤Ï access_num ¤ò¥Ç¥¯¥ê¥á¥ó¥È¤·¤Æ¤¤¤ë¤À¤±¤Ê¤Î¤Ç¡¢¾ï¤Ë 0 ¤òÊÖ¤·¤Þ¤¹¡£
access_num Áàºî¤ÎÁ°¸å¤Ç¥¹¥Ô¥ó¥í¥Ã¥¯¤Î½èÍý¤ò¤·¤Æ¤¤¤Þ¤¹¤¬¡¢ chardev.c ¤Î¾ì¹ç¤Ï¼ÂºÝ¤Ë¤Ï¥¹¥Ô¥ó¥í¥Ã¥¯¤ò¼èÆÀ¤¹¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¡£
- 67 ¡Á 99 ¹ÔÌÜ ( chardev_read )
¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¤Î read ¤ËÂбþ¤¹¤ë´Ø¿ô¤Ç¤¹¡£linux/fs.h Æâ¤Î struct file_operations ¤Î¥á¥ó¥Ð¤Ç¤¢¤ë read ´Ø¿ô¥Ý¥¤¥ó¥¿¤Î·Á¼°¤ÇÄêµÁ¤¹¤ë ɬÍפ¬¤¢¤ê¤Þ¤¹¡£¥¨¥é¡¼½ªÎ»»þ¤ÎÊÖµÑÃͤËÂФ·¤Æ¤Ï chardev_open ¤ÈƱ¤¸¤Ç¤¹¡£ Àµ¾ï½ªÎ»»þ¤Ï¡¢¥æ¡¼¥¶¥×¥í¥»¥¹¤ËÊÖ¤¹¥Ç¡¼¥¿¤Î¥Ð¥¤¥È¿ô¤òÊÖ¤·¤Þ¤¹¡£
°ú¿ô¤Î buf ¤¬·ë²Ì¤ò³ÊǼ¤¹¤ë¤¿¤á¤Î¥æ¡¼¥¶¶õ´Ö¤Î¥Ð¥Ã¥Õ¥¡¤Ç¡¢count ¤¬Í׵ᤵ¤ì¤¿ÆɤߤÀ¤·¥Ð¥¤¥È¿ô¤Ç¤¹¡£¤³¤³¤Ç¤Ï¡¢count ¤¬¸½ºß¤Î³ÊǼ¥Ð¥¤¥È¿ô ¤è¤êÂ礤¤¾ì¹ç¤ÏÆâÉô¥Ð¥Ã¥Õ¥¡¥µ¥¤¥º¤Î¡¢¤½¤ì°Ê³°¤Ï count ¥Ð¥¤¥È¤Î¥Ç¡¼¥¿¤ò ¥æ¡¼¥¶¥×¥í¥»¥¹¤ËÊÖ¤·¤Æ¤¤¤Þ¤¹¡£¥«¡¼¥Í¥ë¶õ´Ö¤È¥æ¡¼¥¶¥×¥í¥»¥¹¶õ´Ö¤Ç¤Ï ¥¢¥É¥ì¥¹ÂηϤ¬°Û¤Ê¤ë¤¿¤á¡¢Ã±¤Ë buf ¤Ë¥³¥Ô¡¼¤¹¤ë¤ï¤±¤Ë¤Ï¤¤¤¤Þ¤»¤ó¡£ ¤³¤Î¾ì¹ç¡¢copy_to_user ¤È¤¤¤¦´Ø¿ô¤ò»È¤¤¤Þ¤¹¡£
#include <asm/uaccess.h> unsigned long copy_to_user( void* to, const void* from, unsigned long count );
to ¤Ë¥³¥Ô¡¼À襢¥É¥ì¥¹¡¢from ¤Ë¥³¥Ô¡¼¸µ¥¢¥É¥ì¥¹¤ò»ØÄꤷ¤Þ¤¹¡£¤Þ¤¿¡¢ count ¤Ë¥³¥Ô¡¼¤¹¤ë¥Ð¥¤¥È¿ô¤ò»ØÄꤷ¤Þ¤¹¡£Ìá¤êÃͤϥ³¥Ô¡¼¤µ¤ì¤Æ¤¤¤Ê¤¤ ¥Ð¥¤¥È¿ô¤Ç¤¢¤ë¤¿¤á¡¢Àµ¾ï¤Ë½ªÎ»¤·¤¿¾ì¹ç¤Ï 0 ¤¬ÊÖ¤ê¤Þ¤¹¡£
¥³¥Ô¡¼¤·¤¿¸å¤Ï¡¢¥³¥Ô¡¼¤·¤¿¥Ç¡¼¥¿Ä¹¤Ë±þ¤¸¤ÆÆâÉô¥Ð¥Ã¥Õ¥¡Æâ¤Î¥Ç¡¼¥¿¤ò ÀèƬ¤ËµÍ¤á¤Æ¤¤¤Þ¤¹¡£¤Ê¤ª¡¢chardev.c ¤Ï read ¼Â¹Ô»þ¤ËÊÖ¤¹¥Ç¡¼¥¿¤¬Ìµ¤¤¾ì¹ç¤Ç¤â ¥Ö¥í¥Ã¥¯¤¹¤ë¤³¤È¤Ï¤¢¤ê¤Þ¤»¤ó¡£¥Ö¥í¥Ã¥¯ I/O ¤Ë¤Ä¤¤¤Æ¤Ïº£¸å¿¨¤ì¤ëͽÄê ¤Ç¤¹¡£
¤Ê¤ª¡¢ºÇ½é¤Î°ú¿ô¤Ç¤¢¤ë struct file* filp ¤Ï¡¢¥ª¡¼¥×¥ó¤µ¤ì¤Æ¤¤¤ë ¥Õ¥¡¥¤¥ë¾ðÊ󤬳ÊǼ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£Î㤨¤Ð¡¢¥Õ¥¡¥¤¥ë¤ÎÆɤ߽ñ¤¥â¡¼¥É¤ä¸½ºß¤Î¥Ý¥¤¥ó¥¿°ÌÃÖ ¤È¤¤¤Ã¤¿ÆâÍƤ¬³ÊǼ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¤Þ¤¿¡¢ºÇ¸å¤Î°ú¿ô¤Ç¤¢¤ë loff_t* pos ¤Ï¡¢¸½ºß¥¢¥¯¥»¥¹¤·¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë¤Î°ÌÃ֤Ǥ¹¡£¥³¥Ô¡¼Ä¾¸å¤Ë¡¢¥³¥Ô¡¼Ä¹¤À¤±¿Ê¤á¤Æ¤¤¤Þ¤¹¡£ °ÌÃÖ¤¬ÌäÂê¤È¤Ê¤ë¥Ç¡¼¥¿¤ò°·¤¦¥É¥é¥¤¥Ð¤Î¾ì¹ç¤Ï¡¢¤³¤ÎÃͤ¬¼¨¤¹¾ì½ê¤«¤é¤Î¥Ç¡¼¥¿¤ò ÊÖ¤¹É¬Íפ¬¤¢¤ê¤Þ¤¹¡£
- 102 ¡Á 134 ¹ÔÌÜ ( chardev_write )
¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¤Î write ¤ËÂбþ¤¹¤ë´Ø¿ô¤Ç¤¹¡£linux/fs.h Æâ¤Î struct file_operations ¤Î¥á¥ó¥Ð¤Ç¤¢¤ë write ´Ø¿ô¥Ý¥¤¥ó¥¿¤Î·Á¼°¤ÇÄêµÁ¤¹¤ë ɬÍפ¬¤¢¤ê¤Þ¤¹¡£¥¨¥é¡¼½ªÎ»»þ¤ÎÊÖµÑÃͤËÂФ·¤Æ¤Ï chardev_open ¤ÈƱ¤¸¤Ç¤¹¡£Àµ¾ï½ªÎ»»þ¤Ï¡¢¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é½ñ¤¹þ¤Þ¤ì¤¿¥Ç¡¼¥¿¤Î¥Ð¥¤¥È¿ô¤òÊÖ¤·¤Þ¤¹¡£
°ú¿ô¤Î buf ¤¬ÆâÉô¥Ð¥Ã¥Õ¥¡¤Ë³ÊǼ¤¹¤ë¤¿¤á¤Î¥Ç¡¼¥¿¤òɽ¤¹¥æ¡¼¥¶¶õ´Ö¤Î¥Ð¥Ã¥Õ¥¡¤Ç¡¢ count ¤¬Í׵ᤵ¤ì¤¿½ñ¤¹þ¤ß¥Ð¥¤¥È¿ô¤Ç¤¹¡£¤³¤³¤Ç¤Ï¡¢ÆâÉô¥Ð¥Ã¥Õ¥¡¤Î ¶õ¤¥Ð¥¤¥È¿ô¤À¤± buf ¤«¤é¥Ç¡¼¥¿¤òÆɤ߹þ¤ß¡¢ÆâÉô¥Ð¥Ã¥Õ¥¡¤Ë½ñ¤¹þ¤ó¤Ç¤¤¤Þ¤¹¡£ ÆâÉô¥Ð¥Ã¥Õ¥¡¤Ë¶õ¤¤¬Ìµ¤¤¾ì¹ç¤Ï¡¢ENOSPC ¤òÊÖ¤·¤Æ¤¤¤Þ¤¹¡£
¤³¤³¤Ç¤âñ¤Ë buf ¤«¤é¥³¥Ô¡¼¤¹¤ë¤ï¤±¤Ë¤Ï¤¤¤¤Þ¤»¤ó¡£¤³¤Î¾ì¹ç¡¢ copy_from_user ¤È¤¤¤¦´Ø¿ô¤ò»È¤¤¤Þ¤¹¡£
#include <asm/uaccess.h> unsigned long copy_from_user( void* to, const void* from, unsigned long count );
to ¤Ë¥³¥Ô¡¼À襢¥É¥ì¥¹¡¢from ¤Ë¥³¥Ô¡¼¸µ¥¢¥É¥ì¥¹¤ò»ØÄꤷ¤Þ¤¹¡£¤Þ¤¿¡¢ count ¤Ë¥³¥Ô¡¼¤¹¤ë¥Ð¥¤¥È¿ô¤ò»ØÄꤷ¤Þ¤¹¡£Ìá¤êÃͤϥ³¥Ô¡¼¤µ¤ì¤Æ¤¤¤Ê¤¤ ¥Ð¥¤¥È¿ô¤Ç¤¢¤ë¤¿¤á¡¢Àµ¾ï¤Ë½ªÎ»¤·¤¿¾ì¹ç¤Ï 0 ¤¬ÊÖ¤ê¤Þ¤¹¡£
filp¡¢pos ¤Ë¤Ä¤¤¤Æ¤Ï chardev_read ¤ÈƱÍͤǤ¹¡£
- 137 ¡Á 144 ¹ÔÌÜ
¥â¥¸¥å¡¼¥ëÆâ¤Î³Æ´Ø¿ô¤È¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¤ÎÁàºî¤ò´ØÏ¢ÉÕ¤±¤ë¤¿¤á¤Ë¤Ï¡¢ linux/fs.h Æâ¤Î struct file_operations ·¿¹½Â¤ÂΤòºîÀ®¤·¡¢¥«¡¼¥Í¥ë¤Ë ÅÐÏ¿¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£¥«¡¼¥Í¥ë 2.4.19 ¤Î linux/fs.h ¤Ç¤Ï¡¢ °Ê²¼¤ÎÍͤËÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£
struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) ( struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*writev) ( struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*sendpage) ( struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); };
¤³¤ÎÃæ¤Ç¡¢´ØÏ¢ÉÕ¤±¤ò¹Ô¤¤¤¿¤¤¥á¥ó¥Ð¤Ë´Ø¿ô¥Ý¥¤¥ó¥¿¤òÀßÄꤷ¡¢Â¾¤Î¥á¥ó¥Ð¤Ë¤Ï NULL ¤òÀßÄꤷ¤Þ¤¹¡£ ¤¿¤À¤·¾åµ¤Î¥á¥ó¥Ð¤ÎÃæ¤Ç struct module * owner ¥á¥ó¥Ð¤Ï¡¢ ¥Õ¥¡¥¤¥ëÁàºî¤È¤Î´ØÏ¢ÉÕ¤±¤ò¹Ô¤¦¤¿¤á¤Î´Ø¿ô¥Ý¥¤¥ó¥¿¤Ç¤Ï¤Ê¤¯¡¢ ¥«¡¼¥Í¥ë¥â¥¸¥å¡¼¥ë¼«¿È¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤¿¤á¤Î¥á¥ó¥Ð¤Ç¤¹¡£ ¤½¤Î¤¿¤á¡¢ÊÌÅÓ½é´ü²½¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£¥«¡¼¥Í¥ë 2.4 ¤Ç¤Ï¡¢THIS_MODULE ¤È¤¤¤¦Ãͤǽé´ü²½¤¹¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡£
chardev.c ¤Ç¤Ï¡¢Á´¥á¥ó¥Ð¤ËÃͤòÀßÄꤹ¤ë¤Î¤Ç¤Ï¤Ê¤¯¡¢gcc ¤Î³ÈÄ¥µ¡Ç½ ¤Ç¤¢¤ë¹½Â¤ÂΤΥ¿¥°ÉÕ¤½é´ü²½¤ò»ÈÍѤ·¤Æ¤¤¤Þ¤¹¡£"¥á¥ó¥Ð̾ :" ¤È¤¤¤¦¥é ¥Ù¥ë¤Ë³¤±¤ÆÃͤòµ½Ò¤·¤Æ¤¤¤¤Þ¤¹¡£¤³¤ÎÍͤˤ¹¤ë¤È¡¢É¬Íפʲսê¤À¤±Àß Äꤹ¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡£
- 147 ¡Á 163 ¹ÔÌÜ ( init_module )
¼«Ê¬¼«¿È¤ò¥¥ã¥é¥¯¥¿¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð¤È¤·¤Æ¥«¡¼¥Í¥ë¤ËÅÐÏ¿¤¹¤ë¤¿¤á¤Ë¡¢ register_chrdev ¤ò¼Â¹Ô¤·¤Æ¤¤¤Þ¤¹¡£
#include <linux/fs.h> int register_chrdev( unsigned int major, const char* name, struct file_operations* fops );
major ¤Ï¥á¥¸¥ã¡¼Èֹ桢name ¤ÏǤ°Õ¤Î¥É¥é¥¤¥Ð̾¾Î¡¢fops ¤Ï¥Õ¥¡¥¤¥ëÁàºî¤È´Ø¿ô¤Î´ØÏ¢¥Æ¡¼¥Ö¥ë¤Î¥¢¥É¥ì¥¹¤Ç¤¹¡£ ÊÖ¤êÃͤ¬Éé¤Î¾ì¹ç¤Ï¥¨¥é¡¼½ªÎ»¤Ç¤¹¡£major ¤Ë 0 °Ê³°¤ò»ØÄꤷ¤ÆÀµ¾ï¤Ë½ªÎ» ¤·¤¿¾ì¹ç¤Ï 0 ¤¬ÊÖ¤ê¤Þ¤¹¡£¤Þ¤¿ major ¤Ë 0 ¤ò»ØÄꤷ¤¿¾ì¹ç¤Ï ¥á¥¸¥ã¡¼ÈÖ¹æ¤ÎưŪ³ä¤êÅö¤Æ¤¬¹Ô¤ï¤ì¡¢¼ÂºÝ¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥á¥¸¥ã¡¼Èֹ椬ÊÖ¤ê¤Þ¤¹¡£
¤Þ¤¿¡¢spin_lock_init ¤Ë¤è¤Ã¤Æ¥¹¥Ô¥ó¥í¥Ã¥¯¤Î½é´ü²½¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
- 166 ¡Á 179 ¹ÔÌÜ ( cleanup_module )
¥«¡¼¥Í¥ë¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë¾ðÊó¤òºï½ü¤¹¤ë¤¿¤á¤Ë¡¢unregister_chrdev ¤ò¼Â¹Ô¤·¤Æ¤¤¤Þ¤¹¡£
#include <linux/fs.h> int unregister_chrdev( unsigned int major, const char* name );
major ¤ÏÅÐÏ¿»þ¤Ë»ØÄꤷ¤¿¥á¥¸¥ã¡¼Èֹ桢name ¤ÏÅÐÏ¿»þ¤Ë»ØÄꤷ¤¿ ¥Ç¥Ð¥¤¥¹Ì¾¾Î¤Ç¤¹¡£Àµ¾ï½ªÎ»»þ¤Ï 0¡¢¤½¤ì°Ê³°¤Ï¥¨¥é¡¼½ªÎ»¤Ç¤¹¡£
°Ê¾å¤Ç chardev.c ¤Î²òÀâ¤Ï½ª¤ï¤ê¤Ç¤¹¡£open / close / read / write ¤È¤¤¤¦´ðËÜŪ¤Ê¥Õ¥¡¥¤¥ëÁàºî¤ËÂбþ¤·¤Æ¤ß¤Þ¤·¤¿¤¬¡¢¤½¤ì¤À¤±¤Ç¤âΩÇÉ¤Ê ¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð¤Ë¸«¤¨¤Æ¤·¤Þ¤¤¤Þ¤¹¡ª¡ÊÁàºî¤·¤Æ¤¤¤ë¥Ï¡¼¥É¥¦¥§¥¢¤Ï¥á¥â¥ê¤À¤±¤Ç¤¹¤¬¡£¡£¡£¡Ë
º£¸å¤Ï¡¢¾¯¤·¤Å¤Ä³ÆÁàºî¤ò³ÈÄ¥¤·¤Æ¤¤¤¤¿¤¤¤È»×¤¤¤Þ¤¹¡£