LECTURE 5 select / poll ¥·¥¹¥Æ¥à¥³¡¼¥ë

¡û ¤Ï¤¸¤á¤Ë

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 ¥·¥¹¥Æ¥à¥³¡¼¥ë¤ËÂбþ¤µ¤»¤Þ¤¹¡£