|
¡û ¤Ï¤¸¤á¤Ë
block.c ¤Ç¤Ï¥Ö¥í¥Ã¥¯ I/O ¤ò¼ÂÁõ¤·¤Æ¤ß¤Þ¤·¤¿¡£¤³¤Î¾ì¹ç¡¢read ¤ä write ¤Ç¥Ö¥í¥Ã¥¯¤·¤Ê¤¤Íͤˤ¹¤ë¤¿¤á¤Ë¤Ï¡¢O_NONBLOCK »ØÄê¤Ç¥Ç¥Ð¥¤¥¹¥Õ¥¡¥¤¥ë¤ò³«¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡£
¤È¤³¤í¤Ç¿¤¯¤Î¥æ¡¼¥¶¥×¥í¥»¥¹¤Ç¤Ï¡¢I/O »þ¤Ë¥Ö¥í¥Ã¥¯¤·¤Æ¤·¤Þ¤ï¤Ê¤¤ÍÍ¤Ë select ¤ä poll ¤È¤¤¤Ã¤¿¥·¥¹¥Æ¥à¥³¡¼¥ë¤ò»È¤Ã¤Æ¡¢¥Ö¥í¥Ã¥¯¤»¤º¤Ë I/O ¤ò¼Â¹Ô¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤Æ¤«¤é I/O ½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£
¤³¤³¤Ç¤Ï¡¢block.c ¤ò²þ¤¤·¤Æ select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ËÂбþ¤µ¤»¤Æ¤ß¤Þ¤·¤ç¤¦¡£
¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à
select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ËÂбþ¤·¤¿¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à poll.c ¤Ç¤¹¡£ ¤Ï¤¸¤á¤Ë ¤Î¥Ú¡¼¥¸¤«¤é¡¢ Á´¤Æ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ò ¸Ç¤á¤¿ tar ¥Ü¡¼¥ë¤ò¥À¥¦¥ó¥í¡¼¥É¤¹¤ë¤³¤È¤â¤Ç¤¤Þ¤¹¡£
´Êñ¤Ê»î¸³¥×¥í¥°¥é¥à poll_test.c ¤âÍÑ°Õ¤·¤Æ¤ß¤Þ¤·¤¿¡£ poll.c ¤ò¥³¥ó¥Ñ¥¤¥ë¤·¤Æ insmod ¤ÇÁȤ߹þ¤ß¡¢/dev/chardev ¤Ë²¿¤â½ñ¤¹þ¤Þ¤º¤Ë poll_test.c ¤Î¼Â¹Ô¥×¥í¥°¥é¥à¤ò¼Â¹Ô¤¹¤ë¤È¡¢
Calling select() ...
¤Èɽ¼¨¤·¤¿¤Þ¤ÞÄä»ß¤·¤Þ¤¹¡£¤½¤Î¾õÂÖ¤ÇÊ̤Υ³¥ó¥½¡¼¥ëÅù¤«¤é
echo "HELLO WORLD" > /dev/chardev
¤ÎÍͤˤ·¤Æ½ñ¤¹þ¤ß¤ò¹Ô¤¦¤È¡¢Ää»ß¤·¤Æ¤¤¤¿¥×¥í¥»¥¹¤¬Æ°ºî¤òºÆ³«¤·¤Æ
Now possible to read()
¤Èɽ¼¨¤·¤Þ¤¹¡£¤½¤Î¸å¤Þ¤¿ Calling select() ... ¤Îɽ¼¨¤ËÌá¤Ã¤ÆÄä»ß¤·¤Þ¤¹¡Ê¤³¤Îή¤ì¤ò 5 ²ó·«¤êÊÖ¤·¤Þ¤¹¡Ë¡£
--- poll.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/kernel.h> /* printk() */ 6 #include <linux/module.h> 7 #include <linux/poll.h> /* POLLIN ... */ 8 #include <linux/wait.h> /* wait_queue_head_t */ 9 #include <linux/sched.h> /* wait_event_interruptible, wake_up_interruptible */ 10 11 12 MODULE_AUTHOR( "Ryo" ); 13 MODULE_DESCRIPTION( "Sample character device driver." ); 14 MODULE_LICENSE( "GPL" ); 15 16 17 static int devmajor = 77; 18 static char* devname = "chardev"; 19 static char* msg = "module [poll.o]"; 20 21 22 #define MAXBUF 32 23 static unsigned char devbuf[ MAXBUF ]; 24 static int buf_pos; 25 26 static struct semaphore chardev_sem; 27 static wait_queue_head_t write_q; 28 static wait_queue_head_t read_q; 29 30 31 /* 32 * ¥í¥°½ÐÎÏ¥Õ¥©¡¼¥Þ¥Ã¥ÈÍÑ´Ø¿ô 33 */ 34 static void 35 log_format( char* body ) 36 { 37 if ( current != NULL ) { 38 printk( KERN_INFO "%s : PID = %-5i cmdline = \"%-10s\" : %s\n", 39 msg, current->pid, current->comm, body ); 40 } 41 else { 42 printk( KERN_INFO "%s : %s\n", msg, body ); 43 } 44 } 45 46 47 /* 48 * open() 49 */ 50 static int 51 chardev_open( struct inode* inode, struct file* filp ) 52 { 53 log_format( "open() called" ); 54 return 0; 55 } 56 57 58 /* 59 * release() 60 */ 61 static int 62 chardev_release( struct inode* inode, struct file* filp ) 63 { 64 log_format( "close() called" ); 65 return 0; 66 } 67 68 69 /* 70 * read() 71 * ¥æ¡¼¥¶¥×¥í¥»¥¹¤ËÂФ·¤ÆÆâÉô¥Ð¥Ã¥Õ¥¡¤ÎÆâÍƤòžÁ÷¤¹¤ë¡£ 72 * žÁ÷¤·¤¿ÆâÍƤÏÆâÉô¥Ð¥Ã¥Õ¥¡¤«¤é¾Ã¤¨¤ë¡£ 73 */ 74 static ssize_t 75 chardev_read( struct file* filp, char* buf, size_t count, loff_t* pos ) 76 { 77 int copy_len; 78 int i; 79 80 log_format( "read() called" ); 81 82 if ( down_interruptible( &chardev_sem ) ) { 83 log_format( "down_interruptible for read failed" ); 84 return -ERESTARTSYS; 85 } 86 87 while ( buf_pos == 0 ) { 88 up( &chardev_sem ); 89 90 if ( filp->f_flags & O_NONBLOCK ) { 91 log_format( "read return because O_NONBLOCK is specified" ); 92 return -EAGAIN; 93 } 94 95 log_format( "read process going to sleep" ); 96 97 if ( wait_event_interruptible( read_q, ( buf_pos != 0 ) ) ) 98 return -ERESTARTSYS; 99 100 if ( down_interruptible( &chardev_sem ) ) { 101 log_format( "down_interruptible for read failed" ); 102 return -ERESTARTSYS; 103 } 104 } 105 106 107 log_format( "read process going to read" ); 108 109 if ( count > buf_pos ) 110 copy_len = buf_pos; 111 else 112 copy_len = count; 113 114 if ( copy_to_user( buf, devbuf, copy_len ) ) { 115 up( &chardev_sem ); 116 log_format( "copy_to_user failed" ); 117 return -EFAULT; 118 } 119 120 *pos += copy_len; 121 122 for ( i = copy_len; i < buf_pos; i ++ ) 123 devbuf[ i - copy_len ] = devbuf[i]; 124 125 buf_pos -= copy_len; 126 127 up( &chardev_sem ); 128 wake_up_interruptible( &write_q ); 129 130 return copy_len; 131 } 132 133 134 /* 135 * write() 136 * ¥æ¡¼¥¶¥×¥í¥»¥¹¤«¤éžÁ÷¤µ¤ì¤¿ÆâÍƤòÆâÉô¥Ð¥Ã¥Õ¥¡¤Ë½ñ¤¹þ¤à¡£ 137 */ 138 static ssize_t 139 chardev_write( struct file* filp, const char* buf, size_t count, loff_t* pos ) 140 { 141 int copy_len; 142 143 log_format( "write() called" ); 144 145 if ( down_interruptible( &chardev_sem ) ) { 146 log_format( "down_interruptible for write failed" ); 147 return -ERESTARTSYS; 148 } 149 150 while ( buf_pos == MAXBUF ) { 151 up( &chardev_sem ); 152 153 if ( filp->f_flags & O_NONBLOCK ) { 154 log_format( "write return because O_NONBLOCK is specified" ); 155 return -EAGAIN; 156 } 157 158 log_format( "write process going to sleep" ); 159 160 if ( wait_event_interruptible( write_q, ( buf_pos != MAXBUF ) ) ) 161 return -ERESTARTSYS; 162 163 if ( down_interruptible( &chardev_sem ) ) { 164 log_format( "down_interruptible for write failed" ); 165 return -ERESTARTSYS; 166 } 167 } 168 169 170 log_format( "write process going to write" ); 171 172 if ( count > ( MAXBUF - buf_pos ) ) 173 copy_len = MAXBUF - buf_pos; 174 else 175 copy_len = count; 176 177 if ( copy_from_user( devbuf + buf_pos, buf, copy_len ) ) { 178 up( &chardev_sem ); 179 log_format( "copy_from_user failed" ); 180 return -EFAULT; 181 } 182 183 *pos += copy_len; 184 buf_pos += copy_len; 185 186 up( &chardev_sem ); 187 wake_up_interruptible( &read_q ); 188 189 return copy_len; 190 } 191 192 193 /* 194 * poll() 195 * select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ëȯ¹Ô»þ¤Ë¼Â¹Ô¤µ¤ì¤ë¡£ 196 */ 197 static unsigned int 198 chardev_poll( struct file* filp, poll_table* wait ) 199 { 200 unsigned int retmask = 0; 201 202 log_format( "poll() called" ); 203 204 poll_wait( filp, &read_q, wait ); 205 poll_wait( filp, &write_q, wait ); 206 207 if ( buf_pos != 0 ) { 208 retmask |= ( POLLIN | POLLRDNORM ); 209 log_format( "POLLIN | POLLRDNORM" ); 210 } 211 212 if ( buf_pos != MAXBUF ) { 213 retmask |= ( POLLOUT | POLLWRNORM ); 214 log_format( "POLLOUT | POLLWRNORM" ); 215 } 216 217 /* 218 Æɤ߹þ¤ß¥Ç¥Ð¥¤¥¹¤¬ EOF ¤Î¾ì¹ç¤Ï retmask ¤Ë POLLHUP ¤òÀßÄê 219 ¥Ç¥Ð¥¤¥¹¤¬¥¨¥é¡¼¾õÂ֤Ǥ¢¤ë¾ì¹ç¤Ï POLLERR ¤òÀßÄê 220 out-of-band ¥Ç¡¼¥¿¤¬Æɤ߽Ф»¤ë¾ì¹ç¤Ï POLLPRI ¤òÀßÄê 221 */ 222 223 return retmask; 224 } 225 226 227 static struct file_operations chardev_fops = 228 { 229 owner : THIS_MODULE, 230 read : chardev_read, 231 write : chardev_write, 232 poll : chardev_poll, 233 open : chardev_open, 234 release : chardev_release, 235 }; 236 237 238 /* 239 * ¥â¥¸¥å¡¼¥ë¤Î½é´ü½èÍý 240 * insmod »þ¤Ë¸Æ¤Ð¤ì¤ë 241 */ 242 int 243 init_module( void ) 244 { 245 if ( register_chrdev( devmajor, devname, &chardev_fops ) ) { 246 log_format( "register_chrdev failed" ); 247 return -EBUSY; 248 } 249 250 sema_init( &chardev_sem, 1 ); 251 252 init_waitqueue_head( &write_q ); 253 init_waitqueue_head( &read_q ); 254 255 log_format( "loaded into kernel" ); 256 return 0; 257 } 258 259 260 /* 261 * ¥â¥¸¥å¡¼¥ë¤Î²òÊü½èÍý 262 * ¥â¥¸¥å¡¼¥ë¤Î»²¾È¿ô¤¬ 0 ¤Ç¤¢¤ì¤Ð¡¢rmmod »þ¤Ë¸Æ¤Ð¤ì¤ë 263 */ 264 void 265 cleanup_module( void ) 266 { 267 if ( unregister_chrdev( devmajor, devname ) ) { 268 log_format( "unregister_chrdev failed" ); 269 /* Âкö̵¤· ... */ 270 } 271 272 log_format( "removed from kernel" ); 273 } 274 275 276 /* End of poll.c */
--- poll_test.c ---
1 #include <fcntl.h> 2 #include <stdio.h> 3 #include <sys/time.h> 4 #include <sys/types.h> 5 #include <unistd.h> 6 7 8 int 9 main( void ) 10 { 11 int cnt = 0; 12 char buf[32]; 13 int fd; 14 fd_set org_set, read_set; 15 16 17 if ( ( fd = open( "/dev/chardev", O_RDWR ) ) < 0 ) { 18 perror( "open" ); 19 exit( 1 ); 20 } 21 22 23 FD_ZERO( &org_set ); 24 FD_SET( fd, &org_set ); 25 26 while ( cnt < 5 ) { 27 read_set = org_set; 28 29 printf( "Calling select() ...\n" ); 30 31 if ( select( fd + 1, &read_set, NULL, NULL, NULL ) < 0 ) { 32 perror( "select" ); 33 close( fd ); 34 exit( 1 ); 35 } 36 37 printf( "Now possible to read()\n" ); 38 read( fd, buf, sizeof( buf ) ); 39 40 cnt ++; 41 } 42 43 close( fd ); 44 return 0; 45 } 46 47 48 /* End of poll_test.c */ 49
¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ÎÀâÌÀ
¤Ç¤Ï¡¢¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤¤¤¤Þ¤¹¡£
poll.c ¤Ï¡¢Á°²ó¤Î block.c ¤ò´ðËܤȤ·¤Æ¡¢select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ëÂбþÍѤνèÍý¤òÄɲ䷤Ƥ¤¤Þ¤¹¡£¤³¤³¤Ç¤ÏÊѹ¹ÅÀ¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Þ¤¹¡£
- 7 ¹ÔÌÜ
select / poll Âбþ½èÍý¤Î¼ÂÁõ¤ËɬÍפʥإåÀ¥Õ¥¡¥¤¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ¤¤¤Þ¤¹¡£
- 193 ¡Á 224 ¹ÔÌÜ ( chardev_poll )
º£²óÄɲä·¤¿´Ø¿ô¤Ç¤¹¡£select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ë¤¬È¯¹Ô¤µ¤ì¤¿ºÝ¤Ë¼Â¹Ô¤µ¤ì¡¢ ¸½ºß¤Î¥Ç¥Ð¥¤¥¹¤Î¾õÂÖ¤òÊÖ¤·¤Þ¤¹¡£¼ÂºÝ¤Ë¤Ï¡¢¸½ºß¤Î¥Ç¥Ð¥¤¥¹¤Î¾õÂ֤˱þ¤¸¤Æ linux/poll.h ¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤ë°Ê²¼¤Î¥Þ¥¯¥íÄêµÁ¤ò»È¤Ã¤¿¥Ó¥Ã¥È¥Þ¥¹¥¯¤ò unsigned int ·¿¤ÎÊÑ¿ô¤ËÀßÄꤷ¤ÆÊÖ¤·¤Þ¤¹¡£
¥Þ¥¯¥í ÀâÌÀ POLLIN ¥Ö¥í¥Ã¥¯¤»¤º¤ËÆɤ߽Ф·²Äǽ POLLRDNORM ( ¥½¥±¥Ã¥ÈÄÌ¿®¤Ë¤ª¤±¤ë out-of-band ¥Ç¡¼¥¿¤ËÂФ·¤Æ ) Ä̾ï¤Î¥Ç¡¼¥¿¤¬Æɤ߽Ф·²Äǽ POLLPRI ¥½¥±¥Ã¥ÈÄÌ¿®¤Ë¤ª¤±¤ë out-of-band ¥Ç¡¼¥¿¤¬¥Ö¥í¥Ã¥¯¤»¤º¤ËÆɤ߽Ф·²Äǽ POLLHUP EOF ¤Ç¤¢¤ë POLLERR ¥Ç¥Ð¥¤¥¹¾å¤Ç¥¨¥é¡¼¤¬È¯À¸¤·¤Æ¤¤¤ë POLLOUT ¥Ö¥í¥Ã¥¯¤»¤º¤Ë½ñ¤¹þ¤ß²Äǽ POLLWRNORM ( ¥½¥±¥Ã¥ÈÄÌ¿®¤Ë¤ª¤±¤ë out-of-band ¥Ç¡¼¥¿¤ËÂФ·¤Æ ) Ä̾ï¤Î¥Ç¡¼¥¿¤¬½ñ¤¹þ¤ß²Äǽ POLLWRBAND ¥½¥±¥Ã¥ÈÄÌ¿®¤Ë¤ª¤±¤ë out-of-band ¥Ç¡¼¥¿¤¬¥Ö¥í¥Ã¥¯¤»¤º¤Ë½ñ¤¹þ¤ß²Äǽ ¤È¤³¤í¤Ç select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ë¤Ï¡¢¤¤¤º¤ì¤«¤Î¥Õ¥¡¥¤¥ëµ½Ò»Ò¤¬ ¥Ö¥í¥Ã¥¯¤»¤º¤Ë½èÍý¤Ç¤¤ëÍͤˤʤë¤Þ¤Ç¡¢¥·¥¹¥Æ¥à¥³¡¼¥ë¼«ÂΤò¥Ö¥í¥Ã¥¯¤µ¤»¤ë ¤³¤È¤¬¤Ç¤¤Þ¤¹¡Ê¤¹¤°¤ËÊÖ¤ëÍͤˤ¹¤ë¤³¤È¤â¤Ç¤¤Þ¤¹¡Ë¡£¥·¥¹¥Æ¥à¥³¡¼¥ë¤¬ Á´¥Õ¥¡¥¤¥ëµ½Ò»Ò¤Î poll ¤ò¼Â¹Ô¤·¤¿·ë²Ì̲¤Ã¤¿¾ì¹ç¡¢²¿¤é¤«¤Î¥¿¥¤¥ß¥ó¥° ¤Çµ¯¤¤ÆºÆÅÙ¥Õ¥¡¥¤¥ëµ½Ò»Ò¤Î¾õÂÖ¤ò¥Á¥§¥Ã¥¯¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£
¤½¤Î¤¿¤á¤Î»ÅÁȤߤòÀßÄꤷ¤Æ¤¤¤ë¤Î¤¬¡¢198¡¢199 ¹ÔÌܤǼ¹Ԥ·¤Æ¤¤¤ë poll_wait ¤Ç¤¹¡£
#include <linux/poll.h> void poll_wait( struct file* file, wait_queue_head_t* queue_p, poll_table* wait );
file ¤È wait ¤Ï chardev_poll ¤Î°ú¿ô¤ò¤½¤Î¤Þ¤ÞÅϤ·¤Þ¤¹¡£queue_p ¤Ë¤Ï¡¢ ¥×¥í¥»¥¹¤òµ¯¤³¤¹¤¿¤á¤ÎÂÔ¤ÁÎó¤òÀßÄꤷ¤Þ¤¹¡£poll.c ¤Î¾ì¹ç¡¢read / write ¼Â¹Ô»þ¤Ë wake_up_interruptible ¤ò¼Â¹Ô¤¹¤ë read_q ¤ª¤è¤Ó write_q ¤ËÂФ·¤Æ poll_wait ¤ò¼Â¹Ô¤·¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢¾õÂÖÊѹ¹¤¬ À¸¤¸ÆÀ¤ë read / write ¼Â¹Ô¤Î¥¿¥¤¥ß¥ó¥°¤Ç select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ë ¤¬Æ°ºî¤òºÆ³«¤·¡¢ºÆÅÙ¾õÂÖ¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤ì¤ëÍͤˤʤê¤Þ¤¹¡£
- 227 ¡Á 235 ¹ÔÌÜ
struct file_opearations ¥Æ¡¼¥Ö¥ë¤Î poll ¥¿¥°¤ËÂФ·¤Æ¡¢¿·¤¿¤Ë chardev_poll ¤Ø¤Î´Ø¿ô¥Ý¥¤¥ó¥¿¤òÀßÄꤷ¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ë¤¬È¯¹Ô¤µ¤ì¤¿ºÝ¤Ë chardev_poll ´Ø¿ô¤¬¼Â¹Ô¤µ¤ì¤Þ¤¹¡£
°Ê¾å¤Ç poll.c ¤Î²òÀâ¤Ï½ª¤ï¤ê¤Ç¤¹¡£¼¡²ó¤Ï¤³¤Î poll.c ¤ò¹¹¤Ë²þ¤¤·¡¢ioctl ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ËÂбþ¤µ¤»¤Þ¤¹¡£