|
¡û ¤Ï¤¸¤á¤Ë
º£²ó¤Ï¡¢¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤éȯ¹Ô¤µ¤ì¤ë ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ËÂбþ¤·¤Æ¤ß¤Þ¤¹¡£ioctl ¤Ï¡¢read ¤ä write ¤Ç¹Ô¤¦¤³¤È¤¬Å¬Åö¤Ç¤Ê¤¤¡¢¥Ç¥Ð¥¤¥¹¤ÎÀßÄê¤òÊѤ¨¤¿¤ê¤¹¤ë¾ì¹ç¤ËÎɤ¯»È¤ï¤ì¤Þ¤¹¡£
¤³¤³¤Ç¤Ï¡¢poll.c ¤ò²þ¤¤·¤Æ ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ËÂбþ¤µ¤»¤Æ¤ß¤Þ¤·¤ç¤¦¡£
¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à
ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ËÂбþ¤·¤¿¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à ioctl.c¡¢ chardev_ioct.h ¤Ç¤¹¡£ ¤Ï¤¸¤á¤Ë ¤Î¥Ú¡¼¥¸¤«¤é¡¢ Á´¤Æ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ò ¸Ç¤á¤¿ tar ¥Ü¡¼¥ë¤ò¥À¥¦¥ó¥í¡¼¥É¤¹¤ë¤³¤È¤â¤Ç¤¤Þ¤¹¡£
´Êñ¤Ê»î¸³¥×¥í¥°¥é¥à ioctl_test.c ¤âÍÑ°Õ¤·¤Æ¤ß¤Þ¤·¤¿¡£ ioctl.c ¤ò¥³¥ó¥Ñ¥¤¥ë¤·¤Æ insmod ¤ÇÁȤ߹þ¤ß¡¢ioctl_test.c ¤Î¼Â¹Ô¥×¥í¥°¥é¥à¤ò¼Â¹Ô¤¹¤ë¤È
Tell driver to update internal value ... Query driver internal value ... Internal value = 0 Tell driver to update internal value via pointer ... Query driver internal value via pointer ... Internal value = 1 Reset reference counter ...
¤Èɽ¼¨¤µ¤ì¤Þ¤¹¡£
--- ioctl.c ---
1 #include <asm/semaphore.h> 2 #include <asm/uaccess.h> /* copy_from_user, copy_to_user */ 3 #include <linux/errno.h> 4 #include <linux/fs.h> /* inode, file, file_operations */ 5 #include <linux/ioctl.h> /* ioctl */ 6 #include <linux/kernel.h> /* printk() */ 7 #include <linux/module.h> 8 #include <linux/poll.h> /* POLLIN ... */ 9 #include <linux/wait.h> /* wait_queue_head_t */ 10 #include <linux/sched.h> /* wait_event_interruptible, wake_up_interruptible */ 11 12 #include "chardev_ioctl.h" 13 14 15 MODULE_AUTHOR( "Ryo" ); 16 MODULE_DESCRIPTION( "Sample character device driver." ); 17 MODULE_LICENSE( "GPL" ); 18 19 20 static int devmajor = 77; 21 static char* devname = "chardev"; 22 static char* msg = "module [poll.o]"; 23 24 25 #define MAXBUF 32 26 static unsigned char devbuf[ MAXBUF ]; 27 static int buf_pos; 28 29 static struct semaphore chardev_sem; 30 static wait_queue_head_t write_q; 31 static wait_queue_head_t read_q; 32 33 34 /* 35 * ¥í¥°½ÐÎÏ¥Õ¥©¡¼¥Þ¥Ã¥ÈÍÑ´Ø¿ô 36 */ 37 static void 38 log_format( char* body ) 39 { 40 if ( current != NULL ) { 41 printk( KERN_INFO "%s : PID = %-5i cmdline = \"%-10s\" : %s\n", 42 msg, current->pid, current->comm, body ); 43 } 44 else { 45 printk( KERN_INFO "%s : %s\n", msg, body ); 46 } 47 } 48 49 50 /* 51 * open() 52 */ 53 static int 54 chardev_open( struct inode* inode, struct file* filp ) 55 { 56 log_format( "open() called" ); 57 return 0; 58 } 59 60 61 /* 62 * release() 63 */ 64 static int 65 chardev_release( struct inode* inode, struct file* filp ) 66 { 67 log_format( "close() called" ); 68 return 0; 69 } 70 71 72 /* 73 * read() 74 * ¥æ¡¼¥¶¥×¥í¥»¥¹¤ËÂФ·¤ÆÆâÉô¥Ð¥Ã¥Õ¥¡¤ÎÆâÍƤòžÁ÷¤¹¤ë¡£ 75 * žÁ÷¤·¤¿ÆâÍƤÏÆâÉô¥Ð¥Ã¥Õ¥¡¤«¤é¾Ã¤¨¤ë¡£ 76 */ 77 static ssize_t 78 chardev_read( struct file* filp, char* buf, size_t count, loff_t* pos ) 79 { 80 int copy_len; 81 int i; 82 83 log_format( "read() called" ); 84 85 if ( down_interruptible( &chardev_sem ) ) { 86 log_format( "down_interruptible for read failed" ); 87 return -ERESTARTSYS; 88 } 89 90 while ( buf_pos == 0 ) { 91 up( &chardev_sem ); 92 93 if ( filp->f_flags & O_NONBLOCK ) { 94 log_format( "read return because O_NONBLOCK is specified" ); 95 return -EAGAIN; 96 } 97 98 log_format( "read process going to sleep" ); 99 100 if ( wait_event_interruptible( read_q, ( buf_pos != 0 ) ) ) 101 return -ERESTARTSYS; 102 103 if ( down_interruptible( &chardev_sem ) ) { 104 log_format( "down_interruptible for read failed" ); 105 return -ERESTARTSYS; 106 } 107 } 108 109 110 log_format( "read process going to read" ); 111 112 if ( count > buf_pos ) 113 copy_len = buf_pos; 114 else 115 copy_len = count; 116 117 if ( copy_to_user( buf, devbuf, copy_len ) ) { 118 up( &chardev_sem ); 119 log_format( "copy_to_user failed" ); 120 return -EFAULT; 121 } 122 123 *pos += copy_len; 124 125 for ( i = copy_len; i < buf_pos; i ++ ) 126 devbuf[ i - copy_len ] = devbuf[i]; 127 128 buf_pos -= copy_len; 129 130 up( &chardev_sem ); 131 wake_up_interruptible( &write_q ); 132 133 return copy_len; 134 } 135 136 137 /* 138 * write() 139 * ¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤éžÁ÷¤µ¤ì¤¿ÆâÍƤòÆâÉô¥Ð¥Ã¥Õ¥¡¤Ë½ñ¤¹þ¤à¡£ 140 */ 141 static ssize_t 142 chardev_write( struct file* filp, const char* buf, size_t count, loff_t* pos ) 143 { 144 int copy_len; 145 146 log_format( "write() called" ); 147 148 if ( down_interruptible( &chardev_sem ) ) { 149 log_format( "down_interruptible for write failed" ); 150 return -ERESTARTSYS; 151 } 152 153 while ( buf_pos == MAXBUF ) { 154 up( &chardev_sem ); 155 156 if ( filp->f_flags & O_NONBLOCK ) { 157 log_format( "write return because O_NONBLOCK is specified" ); 158 return -EAGAIN; 159 } 160 161 log_format( "write process going to sleep" ); 162 163 if ( wait_event_interruptible( write_q, ( buf_pos != MAXBUF ) ) ) 164 return -ERESTARTSYS; 165 166 if ( down_interruptible( &chardev_sem ) ) { 167 log_format( "down_interruptible for write failed" ); 168 return -ERESTARTSYS; 169 } 170 } 171 172 173 log_format( "write process going to write" ); 174 175 if ( count > ( MAXBUF - buf_pos ) ) 176 copy_len = MAXBUF - buf_pos; 177 else 178 copy_len = count; 179 180 if ( copy_from_user( devbuf + buf_pos, buf, copy_len ) ) { 181 up( &chardev_sem ); 182 log_format( "copy_from_user failed" ); 183 return -EFAULT; 184 } 185 186 *pos += copy_len; 187 buf_pos += copy_len; 188 189 up( &chardev_sem ); 190 wake_up_interruptible( &read_q ); 191 192 return copy_len; 193 } 194 195 196 /* 197 * poll() 198 * select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ëȯ¹Ô»þ¤Ë¼Â¹Ô¤µ¤ì¤ë¡£ 199 */ 200 static unsigned int 201 chardev_poll( struct file* filp, poll_table* wait ) 202 { 203 unsigned int retmask = 0; 204 205 log_format( "poll() called" ); 206 207 poll_wait( filp, &read_q, wait ); 208 poll_wait( filp, &write_q, wait ); 209 210 if ( buf_pos != 0 ) { 211 retmask |= ( POLLIN | POLLRDNORM ); 212 log_format( "POLLIN | POLLRDNORM" ); 213 } 214 215 if ( buf_pos != MAXBUF ) { 216 retmask |= ( POLLOUT | POLLWRNORM ); 217 log_format( "POLLOUT | POLLWRNORM" ); 218 } 219 220 /* 221 Æɤ߹þ¤ß¥Ç¥Ð¥¤¥¹¤¬ EOF ¤Î¾ì¹ç¤Ï retmask ¤Ë POLLHUP ¤òÀßÄê 222 ¥Ç¥Ð¥¤¥¹¤¬¥¨¥é¡¼¾õÂ֤Ǥ¢¤ë¾ì¹ç¤Ï POLLERR ¤òÀßÄê 223 out-of-band ¥Ç¡¼¥¿¤¬Æɤ߽Ф»¤ë¾ì¹ç¤Ï POLLPRI ¤òÀßÄê 224 */ 225 226 return retmask; 227 } 228 229 230 /* 231 * ioctl() 232 * Ê£¿ô¥×¥í¥»¥¹¤¬Æ±°ìÊÑ¿ô¤òÁàºî¤¹¤ë¤¿¤á¡¢¥»¥Þ¥Õ¥©¤ä¥¹¥Ô¥ó¥í¥Ã¥¯Åù¤Ç¤Î 233 * ¥í¥Ã¥¯¤ò¹Íθ¤¹¤Ù¤¤À¤¬¡¢ioctl ¤Î¼ÂÁõ¤òÎ㼨¤·¤¿¤¤¤À¤±¤Ê¤Î¤Ç¥í¥Ã¥¯¤Ï 234 * °ìÀڻȤäƤ¤¤Ê¤¤¡£¡£¡£ 235 */ 236 static int 237 chardev_ioctl( 238 struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg ) 239 { 240 static int ioctl_value = 0; 241 int ret = 0; 242 243 log_format( "ioctl() called" ); 244 245 switch( cmd ) { 246 case CHARDEV_IOCTL_TELL : 247 log_format( "IOCTL_TELL" ); 248 ioctl_value = arg; 249 break; 250 251 case CHARDEV_IOCTL_SET : 252 log_format( "IOCTL_SET" ); 253 if ( get_user( ioctl_value, ( int* )arg ) ) 254 return -EFAULT; 255 break; 256 257 case CHARDEV_IOCTL_QUERY : 258 log_format( "IOCTL_QUERY" ); 259 return ioctl_value; 260 261 case CHARDEV_IOCTL_GET : 262 log_format( "IOCTL_GET" ); 263 if ( put_user( ioctl_value, ( int* )arg ) ) 264 return -EFAULT; 265 break; 266 267 case CHARDEV_IOCTL_RESET : 268 log_format( "IOCTL_RESET" ); 269 270 while ( MOD_IN_USE ) 271 MOD_DEC_USE_COUNT; 272 273 MOD_INC_USE_COUNT; 274 break; 275 276 default: 277 return -EINVAL; 278 /* POSIX ɸ½à¤Ç¤Ï -ENOTTY ¤é¤·¤¤ */ 279 } 280 281 return 0; 282 } 283 284 285 static struct file_operations chardev_fops = 286 { 287 owner : THIS_MODULE, 288 read : chardev_read, 289 write : chardev_write, 290 poll : chardev_poll, 291 ioctl : chardev_ioctl, 292 open : chardev_open, 293 release : chardev_release, 294 }; 295 296 297 /* 298 * ¥â¥¸¥å¡¼¥ë¤Î½é´ü½èÍý 299 * insmod »þ¤Ë¸Æ¤Ð¤ì¤ë 300 */ 301 int 302 init_module( void ) 303 { 304 if ( register_chrdev( devmajor, devname, &chardev_fops ) ) { 305 log_format( "register_chrdev failed" ); 306 return -EBUSY; 307 } 308 309 sema_init( &chardev_sem, 1 ); 310 init_waitqueue_head( &write_q ); 311 init_waitqueue_head( &read_q ); 312 313 log_format( "loaded into kernel" ); 314 return 0; 315 } 316 317 318 /* 319 * ¥â¥¸¥å¡¼¥ë¤Î²òÊü½èÍý 320 * ¥â¥¸¥å¡¼¥ë¤Î»²¾È¿ô¤¬ 0 ¤Ç¤¢¤ì¤Ð¡¢rmmod »þ¤Ë¸Æ¤Ð¤ì¤ë 321 */ 322 void 323 cleanup_module( void ) 324 { 325 if ( unregister_chrdev( devmajor, devname ) ) { 326 log_format( "unregister_chrdev failed" ); 327 /* Âкö̵¤· ... */ 328 } 329 330 log_format( "removed from kernel" ); 331 } 332 333 334 /* End of ioctl.c */
--- chardev_ioctl.h ---
1 #ifndef ___chardev_ioctl_h_included_ 2 #define ___chardev_ioctl_h_included_ 3 4 #include <linux/ioctl.h> 5 6 /* 7 * /dev/chardev ¤ËÂФ¹¤ë ioctl() ¥³¥Þ¥ó¥É¤Ë»È¤¦¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼ 8 * 9 * /usr/src/linux/Documentation/ioctl-number.txt ¤Ëµ½Ò¤µ¤ì¤Æ¤¤¤ë 10 * Code ¤È¤Ö¤Ä¤«¤é¤Ê¤¤¤â¤Î¤òÁª¤Ö 11 */ 12 #define CHARDEV_IOCTL_MAGIC 0xAE 13 14 15 #define CHARDEV_IOCTL_TELL _IOC( _IOC_NONE, CHARDEV_IOCTL_MAGIC, 0, 0 ) 16 #define CHARDEV_IOCTL_SET _IOC( _IOC_WRITE, CHARDEV_IOCTL_MAGIC, 1, sizeof( int ) ) 17 #define CHARDEV_IOCTL_QUERY _IOC( _IOC_NONE, CHARDEV_IOCTL_MAGIC, 2, 0 ) 18 #define CHARDEV_IOCTL_GET _IOC( _IOC_READ, CHARDEV_IOCTL_MAGIC, 3, sizeof( int ) ) 19 #define CHARDEV_IOCTL_RESET _IOC( _IOC_NONE, CHARDEV_IOCTL_MAGIC, 4, 0 ) 20 21 22 #endif 23 24 25 /* End of chardev_ioctl.h */
--- ioctl_test.c ---
1 #include <fcntl.h> 2 #include <stdlib.h> 3 #include <sys/ioctl.h> 4 5 #include "chardev_ioctl.h" 6 7 8 int 9 main( void ) 10 { 11 int setval = 0; 12 int retval; 13 int fd; 14 15 if ( ( fd = open( "/dev/chardev", O_RDWR ) ) < 0 ) { 16 perror( "open" ); 17 exit( 1 ); 18 } 19 20 21 /* 22 * IOCTL_TELL 23 */ 24 printf( "Tell driver to update internal value ...\n" ); 25 26 if ( ioctl( fd, CHARDEV_IOCTL_TELL, setval ) == -1 ) 27 perror( "ioctl( CHARDEV_IOCTL_TELL )" ); 28 29 30 /* 31 * IOCTL_QUERY 32 */ 33 printf( "Query driver internal value ...\n" ); 34 35 if ( ( retval = ioctl( fd, CHARDEV_IOCTL_QUERY ) ) == -1 ) 36 perror( "ioctl( CHARDEV_IOCTL_QUERY )" ); 37 38 printf( "Internal value = %d\n", retval ); 39 setval = retval + 1; 40 41 42 /* 43 * IOCTL_SET 44 */ 45 printf( "Tell driver to update internal value via pointer ...\n" ); 46 47 if ( ioctl( fd, CHARDEV_IOCTL_SET, &setval ) == -1 ) 48 perror( "ioctl( CHARDEV_IOCTL_SET )" ); 49 50 51 /* 52 * IOCTL_GET 53 */ 54 printf( "Query driver internal value via pointer ...\n" ); 55 56 if ( ioctl( fd, CHARDEV_IOCTL_GET, &retval ) == -1 ) 57 perror( "ioctl( CHARDEV_IOCTL_GET )" ); 58 59 printf( "Internal value = %d\n", retval ); 60 61 62 /* 63 * IOCTL_RESET 64 */ 65 printf( "Reset reference counter ...\n" ); 66 67 if ( ioctl( fd, CHARDEV_IOCTL_RESET ) == -1 ) 68 perror( "ioctl( CHARDEV_IOCTL_RESET )" ); 69 70 71 close( fd ); 72 return 0; 73 } 74 75 76 /* End of ioctl_test.c */
¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ÎÀâÌÀ
¤Ç¤Ï¡¢¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤¤¤¤Þ¤¹¡£
ioctl.c ¤Ï¡¢Á°²ó¤Î poll.c ¤ò´ðËܤȤ·¤Æ¡¢ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ëÂбþÍѤνèÍý¤òÄɲ䷤Ƥ¤¤Þ¤¹¡£¤³¤³¤Ç¤ÏÊѹ¹ÅÀ¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Þ¤¹¡£
- 5¡¢12 ¹ÔÌÜ
ioctl Âбþ½èÍý¤Î¼ÂÁõ¤ËɬÍפʥإåÀ¥Õ¥¡¥¤¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ¤¤¤Þ¤¹¡£ 12 ¹ÔÌܤǤϡ¢ioctl ¥³¥Þ¥ó¥ÉÄê¿ô¤òÄêµÁ¤·¤¿¼«ºî¤Î¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ¤¤¤Þ¤¹¡£
¥æ¡¼¥¶¥×¥í¥»¥¹¤Ç»ÈÍѤ¹¤ë ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ë¤Î´Ø¿ô¥×¥í¥È¥¿¥¤¥×¤Ï
#include <sys/ioctl.h> int ioctl( int fd, int request, ... );
¤ÎÍͤˤʤê¤Þ¤¹¡£Âè 2 °ú¿ô¤Ë¥³¥Þ¥ó¥É¤ò»ØÄꤹ¤ëÄê¿ô¤ò¡¢Âè 3 °ú¿ô¤Ë ¥³¥Þ¥ó¥É¤Î°ú¿ô¤òľÀÜÃͤȤ·¤Æ¡¢¤¢¤ë¤¤¤Ï¥Ý¥¤¥ó¥¿¤ò²ð¤·¤Æ¥Ç¡¼¥¿¤òÅϤ·¤Þ¤¹ ( °ú¿ô¤¬Ìµ¤¯¤Æ¤âÎɤ¤ )¡£
chardev_ioctl.h ¤Ç¤Ï°Ê²¼¤Î ioctl ¥³¥Þ¥ó¥ÉÄê¿ô¤òÄêµÁ¤·¤Æ¤¤¤Þ¤¹¡£
Äê¿ô̾ ¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¸«¤¿Æþ½ÐÎÏÊý¸þ ioctl Âè3°ú¿ô¤Î·¿ CHARDEV_IOCTL_TELL ½ÐÎÏ ÃÍ CHARDEV_IOCTL_SET ½ÐÎÏ ¥Ý¥¤¥ó¥¿ CHARDEV_IOCTL_QUERY ÆþÎÏ ÃÍ CHARDEV_IOCTL_GET ÆþÎÏ ¥Ý¥¤¥ó¥¿ CHARDEV_IOCTL_RESET ½ÐÎÏ Ìµ¤· CHARDEV_IOCTL_TELL / CHARDEV_IOCTL_SET ¤Ï¤É¤Á¤é¤â¡¢¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð ¤ËÂФ·¤ÆÃͤòÀßÄꤹ¤ë¥³¥Þ¥ó¥É¤Ç¤¹¡£TELL ¤ÏľÀÜÃͤòÄÌÃΤ·¡¢SET ¤Ï¥Ý¥¤¥ó¥¿ ¤òÂè 3 °ú¿ô¤ËÀßÄꤹ¤ëÅÀ¤¬°Û¤Ê¤ê¤Þ¤¹¡£
CHARDEV_IOCTL_QUERY / CHARDEV_IOCTL_GET ¤Ï¤É¤ê¤¿¤â¡¢¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð ¤«¤éÃͤò¼èÆÀ¤¹¤ë¥³¥Þ¥ó¥É¤Ç¤¹¡£QUERY ¤Ï ioctl ¤ÎÊÖ¤êÃͤȤ·¤ÆÃͤò¼èÆÀ¤·¡¢ GET ¤ÏÂè 3 °ú¿ô¤ËÀßÄꤷ¤¿¥Ý¥¤¥ó¥¿¤Î»²¾ÈÀè¤ËÃͤò³ÊǼ¤¹¤ëÅÀ¤¬°Û¤Ê¤ê¤Þ¤¹¡£
CHARDEV_IOCTL_RESET ¤Ï¥Ç¥Ð¥Ã¥°ÍѤΥ³¥Þ¥ó¥É¤Ç¡¢¥«¡¼¥Í¥ë¥â¥¸¥å¡¼¥ë¤Î »²¾È¥«¥¦¥ó¥¿ ( ¥æ¡¼¥¶¥×¥í¥»¥¹¤ä¾¤Î¥«¡¼¥Í¥ë¥â¥¸¥å¡¼¥ëÅù¤«¤é»²¾È¤µ¤ì¤Æ¤¤¤ë ¿ô¤ò´ÉÍý¤¹¤ë¥«¥¦¥ó¥¿ ) ¤ò¡¢¶¯À©Åª¤Ë 1 ¤Ë¤·¤Æ¤·¤Þ¤¤¤Þ¤¹¡£¤³¤ì¤ò¼Â¹Ô¤·¤¿Ä¾¸å¤Ë ¥Õ¥¡¥¤¥ëµ½Ò»Ò¤òÊĤ¸¤Æ¤·¤Þ¤¨¤Ð»²¾È¥«¥¦¥ó¥¿¤Ï 0 ¤Ë¤Ê¤ë¤¿¤á¡¢Â¾¤Ë»²¾È¤·¤Æ¤¤¤ë ¥æ¡¼¥¶¥×¥í¥»¥¹Åù¤¬¤¢¤Ã¤Æ¤â¶¯À©Åª¤Ë rmmod ¤·¤Æ¤·¤Þ¤¦¤³¤È¤¬½ÐÍè¤Þ¤¹¡£
¥æ¡¼¥¶¥×¥í¥»¥¹¤Ë¤ª¤±¤ë¤³¤ì¤é¤Î¥³¥Þ¥ó¥É¤Î¾Ü¤·¤¤»È¤¤Êý¤Ï¡¢ ioctl_test.c ¤ò»²¾È¤·¤Æ²¼¤µ¤¤¡£
¤È¤³¤í¤Ç³Æ¡¹¤Î¥³¥Þ¥ó¥ÉÄê¿ô¤Ï¡¢¥·¥¹¥Æ¥àÁ´ÂΤÇÍ£°ì¤Ë¤Ê¤ë¤³¤È¤¬µá¤á¤é¤ì¤Þ¤¹¡£ ¤½¤Î¤¿¤á¤Ë¤Ï¤Þ¤º¡¢¥«¡¼¥Í¥ë¥½¡¼¥¹¥Ä¥ê¡¼Æâ¤Î Documentation/ioctl-number.txt ¤ò»²¾È¤·¤Æ¡¢»È¤ï¤ì¤Æ¤¤¤Ê¤¤¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤ò·èÄꤷ¤Þ¤¹¡£ chardev_ioctl.h ¤Ç¤Ï¡¢0xAE ¤ò »È¤Ã¤Æ¤¤¤Þ¤¹¡£¤³¤ÎÃͤϡ¢»È¤Ã¤Æ¤¤¤ë¥·¥¹¥Æ¥à¤Ë±þ¤¸¤Æ·èÄꤷ¤Æ²¼¤µ¤¤¡£
¼¡¤Ë¡¢_IOC ¥Þ¥¯¥í¤ò»È¤Ã¤ÆÄê¿ô¤òºî¤ê½Ð¤·¤Þ¤¹¡£
#include <linux/ioctl.h> _IOC( direction, magic, number, size )
direction ¤Ï¥æ¡¼¥¶¥×¥í¥»¥¹¤È¤Î¥Ç¡¼¥¿Å¾Á÷¤ÎÊý¸þ¤ò¡¢°Ê²¼¤ÎÄê¿ô¤Ç»ØÄꤷ¤Þ¤¹¡£
Äê¿ô̾ ¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤é¸«¤¿¥Ç¡¼¥¿Å¾Á÷¤ÎÊý¸þ _IOC_NONE ̵¤· ( ¥Ý¥¤¥ó¥¿¤Ç¤Ï¤Ê¤¯Ä¾ÀÜÃͤò¤ä¤ê¤È¤ê¤¹¤ë¾ì¹ç¤Ï¡¢¤³¤ì¤ò»È¤¦ ) _IOC_READ ÆþÎÏ _IOC_WRITE ½ÐÎÏ _IOC_READ | _IOC_WRITE Æþ½ÐÎÏ magic ¤Ï¡¢ÀèÄø·èÄꤷ¤¿¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤ò»ØÄꤷ¤Þ¤¹¡£number ¤Ï¡¢ ¥³¥Þ¥ó¥É¤ò¼±Ê̤¹¤ë¤¿¤á¤ÎÄÌÈÖ¤ò»ØÄꤷ¤Þ¤¹¡£¥Ó¥Ã¥ÈÉý¤¬ 8 ¥Ó¥Ã¥È¤Ê¤Î¤Ç¡¢ 0 - 255 ¤ò»ØÄꤷ¤Þ¤¹¡£
size ¤Ï¡¢¥Ç¡¼¥¿Å¾Á÷¤òȼ¤¦¾ì¹ç¤ÎžÁ÷¥µ¥¤¥º¤òÀßÄꤷ¤Þ¤¹¡£¤¿¤À¤·¡¢ ¥³¥Þ¥ó¥É¤«¤éžÁ÷¥µ¥¤¥º¤ò¥Ç¥³¡¼¥É¤·¤Æ»È¤¦¤Î¤Ç¤Ê¤±¤ì¤Ð¡¢Ê̤˲¿¤òÀßÄê ¤·¤Æ¤âÎɤ¤¤ß¤¿¤¤¤Ç¤¹¡£
- 230 ¡Á 282 ¹ÔÌÜ ( chardev_ioctl )
º£²óÄɲä·¤¿´Ø¿ô¤Ç¤¹¡£ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ë¤¬È¯¹Ô¤µ¤ì¤¿ºÝ¤Ë¼Â¹Ô¤µ¤ì¤Þ¤¹¡£ switch ʸ¤Ç¥³¥Þ¥ó¥É¤Ë±þ¤¸¤¿½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤ë¤À¤±¤Ç¤¹¡£chardev_ioctl ¤ÎÂè 3 °ú¿ô cmd ¤È¤·¤Æ¥³¥Þ¥ó¥ÉÄê¿ô¤¬¡¢Âè 4 °ú¿ô arg ¤È¤·¤Æ¥æ¡¼¥¶¥×¥í¥»¥¹¤Ç ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ÎÂè 3 °ú¿ô¤ËÀßÄꤷ¤¿ÊÑ¿ô¤¬ÅϤµ¤ì¤Þ¤¹¡£
¥³¥Þ¥ó¥É ½èÍýÆâÍÆ CHARDEV_IOCTL_TELL arg ¤òľÀܤÎÀßÄêÃͤȤ·¤Æ¤¤¤ë¤Î¤Ç¡¢ÆâÉôÊÑ¿ô¤ËÀßÄꤷ¤Þ¤¹¡£ CHARDEV_IOCTL_SET arg ¤ÏÀ°¿ôÊÑ¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤È¤·¤Æ°·¤¤¤Þ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Î»²¾ÈÀ褫¤é ÆâÉôÊÑ¿ô¤Ë¥Ç¡¼¥¿¤òžÁ÷¤¹¤ë¤Î¤Ç¤¹¤¬¡¢read / write ¤Î¼ÂÁõƱÍÍ¡¢Ä¾ÀÜÂåÆþ ¤¹¤ë¤³¤È¤Ï¤Ç¤¤Þ¤»¤ó¡£¤³¤³¤Ç¤Ï¡¢1 / 2 / 4 ¥Ð¥¤¥È¤Î¥Ç¡¼¥¿Å¾Á÷¤ò copy_from_user ¤è¤ê¤âÁ᤯¹Ô¤Ã¤Æ¤¯¤ì¤ë get_user ´Ø¿ô¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡£ get_user ¤ÏÀ®¸ù¤¹¤ë¤È 0¡¢¼ºÇÔ¤¹¤ë¤È -EFAULT ¤òÊÖ¤·¤Þ¤¹¡£ CHARDEV_IOCTL_QUERY ioctl ¤ÎÌá¤êÃͤòÊÖµÑÃͤȤ·¤Æ¤¤¤ë¤Î¤Ç¡¢ÆâÉôÊÑ¿ô¤ÎÃͤò return ¤·¤Þ¤¹¡£ CHARDEV_IOCTL_GET arg ¤ÏÀ°¿ôÊÑ´¹¤Ø¤Î¥Ý¥¤¥ó¥¿¤È¤·¤Æ°·¤¤¤Þ¤¹¡£¤³¤Î¥Ý¥¤¥ó¥¿¤Î»²¾ÈÀè¤ËÂФ·¤Æ¡¢ 1 / 2 / 4 ¥Ð¥¤¥È¤Î¥Ç¡¼¥¿Å¾Á÷¤ò copy_to_user ¤è¤ê¤âÁ᤯¹Ô¤Ã¤Æ¤¯¤ì¤ë put_user ´Ø¿ô¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡£put_user ¤ÏÀ®¸ù¤¹¤ë¤È 0 ¤ò¡¢¼ºÇÔ¤¹¤ë¤È -EFAULT ¤òÊÖ¤·¤Þ¤¹¡£ CHARDEV_IOCTL_RESET ¥«¡¼¥Í¥ë¥â¥¸¥å¡¼¥ë¤Î»²¾È¥«¥¦¥ó¥¿¤ò¡¢¶¯À©Åª¤Ë 1 ¤Ë¤·¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢ ¼Â¹Ô¸å¤Ë¥Õ¥¡¥¤¥ëµ½Ò»Ò¤òÊĤ¸¤ì¤Ð»²¾È¥«¥¦¥ó¥¿¤¬ 0 ¤È¤Ê¤ê¡¢Â¾¥æ¡¼¥¶¥×¥í¥»¥¹ ¤¬»²¾ÈÃæ¤Ç¤¢¤Ã¤Æ¤â rmmod ¤¹¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡£ËÜÅö¤ÎÌÜŪ¤Ï¡¢¥Ð¥°Åù¤Ç »²¾È¥«¥¦¥ó¥¿¤¬¶¸¤Ã¤Æ¤·¤Þ¤¤ rmmod ¤Ç¤¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤Ã¤¿»þ¤Ë»È¤¤¤¿¤¤¤À¤±¤Ç¤¹¡£ MOD_IN_USE ¥Þ¥¯¥í¤Ï¡¢»²¾È¥«¥¦¥ó¥¿¤¬ 0 ¤Ç̵¤¤¾ì¹ç¤Ë¿¿¤Èɾ²Á¤µ¤ì¤Þ¤¹¡£ MOD_DEC_USE_COUNT ¥Þ¥¯¥í¤Ï»²¾È¥«¥¦¥ó¥¿¤ò 1 ¸º»»¤·¡¢ MOD_INC_USE_COUNT ¥Þ¥¯¥í¤Ï»²¾È¥«¥¦¥ó¥¿¤ò 1 Áý²Ã¤·¤Þ¤¹¡£ ¤³¤ì¤é¤ò»È¤¤¡¢»²¾È¥«¥¦¥ó¥¿¤¬ 0 ¤Ë¤Ê¤ë¤Þ¤Ç MOD_DEC_USE_COUNT ¤Ç¸º»»¤·¡¢ ºÇ¸å¤Ë MOD_INC_USE_COUNT ¤Ç 1 ¤Ë¤·¤Æ¤¤¤Þ¤¹¡£
- 285 ¡Á 294 ¹ÔÌÜ
struct file_opearations ¥Æ¡¼¥Ö¥ë¤Î ioctl ¥¿¥°¤ËÂФ·¤Æ¡¢¿·¤¿¤Ë chardev_ioctl ¤Ø¤Î´Ø¿ô¥Ý¥¤¥ó¥¿¤òÀßÄꤷ¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ë¤¬È¯¹Ô¤µ¤ì¤¿ºÝ¤Ë chardev_ioctl ´Ø¿ô¤¬¼Â¹Ô¤µ¤ì¤Þ¤¹¡£
°Ê¾å¤Ç ioctl.c ¤Î²òÀâ¤Ï½ª¤ï¤ê¤Ç¤¹¡£¥¥ã¥é¥¯¥¿¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð¤È¤·¤Æ¤ÎÆâÍƤϤҤȤޤº½ªÎ»¤·¤Æ¡¢¼¡²ó¤«¤é¤Ï¾¤ÎÏÃÂê¤ò¼è¤ê¾å¤²¤¿¤¤¤È»×¤¤¤Þ¤¹¡£