LECTURE 12 /proc ¥¤¥ó¥¿¥Õ¥§¡¼¥¹¤ò»È¤¦

Á°¤Î¥Ú¡¼¥¸¤Ø ¼¡¤Î¥Ú¡¼¥¸¤Ø

¡û ¤Ï¤¸¤á¤Ë

Linux® ¤Ç¤Ï¡¢/proc ¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤È¤¤¤¦¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤¹¡£/proc ¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ï¡¢¼Â¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë¤ï¤±¤Ç¤Ï¤Ê¤¯¡¢¥«¡¼¥Í¥ëÆâ¤Î¥½¥Õ¥È¥¦¥§¥¢¤È¾ðÊó¤Î¤ä¤ê¤È¤ê¤ò¤¹¤ë¤¿¤á¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹¤Ç¤¹¡£Î㤨¤Ð ps Åù¤Ï¡¢/proc °Ê²¼¤Î¥Õ¥¡¥¤¥ë¤«¤é¾ðÊó¤ò¼ý½¸¤·¤Æ²èÌ̤Ëɽ¼¨¤·¤Æ¤¤¤Þ¤¹¡£

¤³¤³¤Ç¤Ï¡¢/proc °Ê²¼¤Ë¥¨¥ó¥È¥ê¤òºîÀ®¤·¡¢¥æ¡¼¥¶¥×¥í¥»¥¹¤È¤ä¤ê¤È¤ê¤¹¤ëÊýË¡¤òÀâÌÀ¤·¤Þ¤¹¡£

¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à

/proc/driver/samplproc ¤È¤¤¤¦ /proc ¥¤¥ó¥¿¥Õ¥§¡¼¥¹¤ËÂбþ¤·¤¿¥µ¥ó¥×¥ë¥×¥í¥°¥é¥àproc.c ¤Ç¤¹¡£¤Ï¤¸¤á¤Ë ¤Î¥Ú¡¼¥¸¤«¤é¡¢Á´¤Æ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ò ¸Ç¤á¤¿ tar ¥Ü¡¼¥ë¤ò¥À¥¦¥ó¥í¡¼¥É¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£

insmod ¤ÇÁȤ߹þ¤à¤È¡¢/proc/driver/sampleproc ¤È¤¤¤¦¥¨¥ó¥È¥ê¤òºîÀ®¤·¤Þ¤¹¡£¤³¤Î¥¨¥ó¥È¥ê¤ËÂФ·¤Æ¡¢LECTURE 3 Ê£¿ô¥×¥í¥»¥¹¤«¤é¤Î¥¢¥¯¥»¥¹ ¤ÎÍÍ¤Ë echo Åù¤Ç½ñ¤­¹þ¤ó¤ÀÆâÍƤò cat ¤ÇÆɤ߹þ¤à¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£

--- proc.c ---

    1    #include <asm/uaccess.h>    /* copy_from_user */
    2    #include <linux/errno.h>
    3    #include <linux/module.h>   /* module ºîÀ®¤Ë¤Ïɬ¿Ü */
    4    #include <linux/kernel.h>   /* printk */
    5    #include <linux/proc_fs.h>
    6    #include <linux/stat.h>     /* S_IFREG, ... */
    7    
    8    
    9    MODULE_LICENSE( "GPL" );
   10    
   11    static char* msg = "module [proc.o]";
   12    
   13    #define MAXBUF 32
   14    static unsigned char procbuf[ MAXBUF ];
   15    static int buf_pos;
   16    
   17    static struct semaphore proc_sem;
   18    
   19    
   20    /*
   21     * /proc/driver/sampleproc ¤ËÂФ·¤ÆÆɤ߽Ф·¤ò¹Ô¤Ã¤¿ºÝ¤Ë¼Â¹Ô¤µ¤ì¤ë¡£
   22     * ÆâÉô¥Ð¥Ã¥Õ¥¡¤ÎÆâÍƤòÊÖ¤¹¡£
   23     */
   24    static int
   25    proc_read( char* page, char** start, off_t offset, int count, int* eof, void* data )
   26    {
   27        int len = 0;
   28    
   29        printk( KERN_INFO "%s : read()  called\n", msg );
   30    
   31        if ( down_interruptible( &proc_sem ) ) {
   32            printk( KERN_INFO "%s : down_interruptible for read failed\n", msg );
   33            return -ERESTARTSYS;
   34        }
   35    
   36        if ( buf_pos != 0 ) {
   37            len += sprintf( page, "%s : Internal buffer contents = %s\n", msg, procbuf );
   38            buf_pos = 0;
   39        }
   40    
   41        up( &proc_sem );
   42    
   43        *eof = 1;
   44        return len;
   45    }
   46    
   47    
   48    /**
   49     * /proc/driver/sampleproc ¤ËÂФ·¤Æ½ñ¤­¹þ¤ß¤ò¹Ô¤Ã¤¿ºÝ¤Ë¼Â¹Ô¤µ¤ì¤ë¡£
   50     * ½ñ¤­¹þ¤Þ¤ì¤¿ÆâÍƤòÆâÉô¥Ð¥Ã¥Õ¥¡¤ËÊÝ»ý¤¹¤ë¡£
   51     */
   52    static int
   53    proc_write( struct file* filp, const char* buffer, unsigned long count, void* data )
   54    {
   55        int copy_len;
   56    
   57        printk( KERN_INFO "%s : write() called\n", msg );
   58    
   59        if ( down_interruptible( &proc_sem ) ) {
   60            printk( KERN_INFO "%s : down_interruptible for write failed\n", msg );
   61            return -ERESTARTSYS;
   62        }
   63    
   64        if ( buf_pos == MAXBUF ) {
   65            up( &proc_sem );
   66            printk( KERN_INFO "%s : no space left\n", msg );
   67            return -ENOSPC;
   68        }
   69    
   70        if ( count > ( MAXBUF - buf_pos ) )
   71            copy_len = MAXBUF - buf_pos;
   72        else
   73            copy_len = count;
   74    
   75        if ( copy_from_user( procbuf + buf_pos, buffer, copy_len ) ) {
   76            up( &proc_sem );
   77            printk( KERN_INFO "%s : copy_from_user failed\n", msg );
   78            return -EFAULT;
   79        }
   80    
   81        buf_pos += copy_len;
   82        up( &proc_sem );
   83    
   84        return copy_len;
   85    }
   86    
   87    
   88    /*
   89     * ¥â¥¸¥å¡¼¥ë¤Î½é´ü½èÍý
   90     * insmod »þ¤Ë¸Æ¤Ð¤ì¤ë
   91     */
   92    int 
   93    init_module( void )
   94    {
   95        struct proc_dir_entry* entry;
   96        entry = create_proc_entry( "driver/sampleproc", 
   97                       S_IFREG | S_IRUGO | S_IWUGO, NULL );
   98    
   99        if ( entry != NULL ) {
  100            entry->read_proc  = proc_read;
  101            entry->write_proc = proc_write;
  102        }
  103        else {
  104            printk( KERN_INFO "%s : create_proc_entry failed\n", msg );
  105            return -EBUSY;
  106        }
  107    
  108        sema_init( &proc_sem, 1 );
  109        printk( KERN_INFO "%s : loaded  into kernel\n", msg );
  110    
  111        return 0;
  112    }
  113    
  114    
  115    /*
  116     * ¥â¥¸¥å¡¼¥ë¤Î²òÊü½èÍý
  117     * ¥â¥¸¥å¡¼¥ë¤Î»²¾È¿ô¤¬ 0 ¤Ç¤¢¤ì¤Ð¡¢rmmod »þ¤Ë¸Æ¤Ð¤ì¤ë
  118     */
  119    void 
  120    cleanup_module( void )
  121    {
  122        remove_proc_entry( "driver/sampleproc", NULL );
  123        printk( KERN_INFO "%s : removed from kernel\n", msg );
  124    }
  125    
  126    
  127    /* End of proc.c */

¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ÎÀâÌÀ

¤Ç¤Ï¡¢¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤¤¤­¤Þ¤¹¡£¼ÂºÝ¤ÎÆɤ߹þ¤ß½èÍý¤ä½ñ¤­¹þ¤ß½èÍý¤Ë¤Ä¤¤¤Æ¤Ï¡¢LECTURE 3 Ê£¿ô¥×¥í¥»¥¹¤«¤é¤Î¥¢¥¯¥»¥¹ ¤È¤Û¤ÜƱÍͤʤΤǡ¢¤½¤Á¤é¤ÎÀâÌÀ¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£¤³¤³¤Ç¤Ï¡¢/proc ¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥àÆÃÍ­¤ÎÆâÍƤˤĤ¤¤ÆÀâÌÀ¤·¤Þ¤¹¡£

  • 1 ¡Á 6 ¹ÔÌÜ

    ɬÍפʥإåÀ¥Õ¥¡¥¤¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ¤¤¤Þ¤¹¡£/proc ¤Ë¥¨¥ó¥È¥ê¤ò ºîÀ®¤¹¤ëºÝ¤Ë¡¢¥Õ¥¡¥¤¥ë¤Î¼ïÎà¤äÆɤ߹þ¤ß¡¿½ñ¹þ¤ß¸¢¤ÎÀßÄê¤ò¹Ô¤¤¤Þ¤¹¤¬¡¢ ¤½¤ÎºÝ¤Ë linux/stat.h ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëÄê¿ô¤ò»ÈÍѤ·¤Þ¤¹¡£

  • 20 ¡Á 45 ¹ÔÌÜ ( proc_read() )

    /proc °Ê²¼¤Î¥¨¥ó¥È¥ê¤ËÂФ·¤ÆÆɤ߽Ф·¤ò¹Ô¤Ã¤¿ºÝ¤Ë¼Â¹Ô¤µ¤ì¤ë´Ø¿ô¤Ç¤¹¡£ ÆɤߤÀ¤·ÍѤδؿô¤Ï¡¢°Ê²¼¤Î·Á¼°¤ÇºîÀ®¤·¤Þ¤¹¡£

    int read_proc( char* page, char** start, off_t off, int count, int* eof, void* data );
    
    

    page ¤Ç»ØÄꤵ¤ì¤¿¥Ð¥Ã¥Õ¥¡¤ËÂФ·¤Æ¡¢ÊÖ¤·¤¿¤¤ÆâÍƤò½ñ¤­¹þ¤ß¤Þ¤¹¡£ page ¤¬¼¨¤¹¥Ð¥Ã¥Õ¥¡¤Ï¡¢¥«¡¼¥Í¥ë¤¬ 1 ¥Ú¡¼¥¸¡Ê x86 ¤Ç¤Ï 4KB ) ¤Î¥Ð¥Ã¥Õ¥¡¤ò ³ä¤êÅö¤Æ¤Þ¤¹¡£¤è¤Ã¤Æ¡¢1 ¥Ú¡¼¥¸¤ò±Û¤¨¤ëÂ礭¤µ¤Î¥Ç¡¼¥¿¤ò½ñ¤­¹þ¤ó¤Ç¤Ï¤¤¤±¤Þ¤»¤ó ¡Ê count ¤ò±Û¤¨¤Ê¤±¤ì¤ÐÂç¾æÉפǤ¹ )¡£

    1 ¥Ú¡¼¥¸¤ò±Û¤¨¤ëÂ礭¤µ¤Î¥Ç¡¼¥¿¤òÊÖ¤¹¾ì¹ç¤Ï start ¤ò¤¦¤Þ¤¯»È¤¦É¬Íפ¬¤¢¤ë¤Î¤Ç¤¹¤¬¡¢ 1 ¥Ú¡¼¥¸Ì¤Ëþ¤Î¾ì¹ç¤Ï start ¤ò̵»ë¤·¤Þ¤¹¡£proc.c ¤Ç¤Ï¡¢¤´¤¯¾®¤µ¤Ê¥Ç¡¼¥¿¤òÊÖ¤¹¤À¤±¤Ç¤¹¤Î¤Ç¡¢ start ¤ò̵»ë¤·¤Æ¤¤¤Þ¤¹¡£É®¼Ô¤Ï¤Þ¤À start ¤Î»È¤¤Êý¤¬¤è¤¯Ê¬¤«¤Ã¤Æ¤¤¤Ê¤¤¤Î¤Ç¡¢ ¤³¤³¤Ç¤Ï¿¨¤ì¤Þ¤»¤ó m(__)m ʬ¤«¤Ã¤¿¤éÀâÌÀ¤òÉÕ¤±²Ã¤¨¤è¤¦¤È»×¤¤¤Þ¤¹¡£

    off ¤Ï¸½ºß¥¢¥¯¥»¥¹¤·¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë¤Î°ÌÃ֤ǡ¢count ¤ÏÆɤ߽Ф·¤òÍ׵ᤷ¤Æ¤¤¤ë ¥Ç¡¼¥¿¤Î¥Ð¥¤¥È¿ô¤Ç¤¹¡£¥Õ¥¡¥¤¥ë¤Î°ÌÃ֤˰ÕÌ£¤¬¤¢¤ë¥Ç¡¼¥¿¤ò°·¤¦¾ì¹ç¤Ï¡¢ off °Ê¹ß¤Î¥Ç¡¼¥¿¤ò½ñ¤­¹þ¤à¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡£

    eof ¤Ï¡¢ÊÖ¤¹¥Ç¡¼¥¿¤¬Ìµ¤¤¾ì¹ç¤ËÆâÉô¤Ç 1 ¤ËÀßÄꤷ¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢¸Æ½Ð¦¤Ç EOF ¤ÈȽÃǤ·¤Æ¤¯¤ì¤Þ¤¹¡£¤Þ¤¿¡¢data ¤Ï /proc ¤Ë¥¨¥ó¥È¥ê¤òºîÀ®¤¹¤ëºÝ¤ËÀßÄꤷ¤¿ ¥Ý¥¤¥ó¥¿¤¬¤½¤Î¤Þ¤ÞÅϤµ¤ì¤Þ¤¹¡£

  • 48 ¡Á 85 ¹ÔÌÜ ( proc_write )

    /proc °Ê²¼¤Î¥¨¥ó¥È¥ê¤ËÂФ·¤Æ½ñ¤­¹þ¤ß¤ò¹Ô¤Ã¤¿ºÝ¤Ë¼Â¹Ô¤µ¤ì¤ë´Ø¿ô¤Ç¤¹¡£ ½ñ¤­¹þ¤ßÍѤδؿô¤Ï¡¢°Ê²¼¤Î·Á¼°¤ÇºîÀ®¤·¤Þ¤¹¡£

    int write_proc( struct file* filp, const char* buffer, unsigned long count, void* data );
    
    

    filp¡¢buffer¡¢count ¤Ë¤Ä¤¤¤Æ¤Ï¡¢Ä̾ï¤Î¥­¥ã¥é¥¯¥¿¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð¤Î write ´Ø¿ô¤ÈƱÍͤΰÕÌ£¤Ç¤¹¡£data ¤Ï¡¢/proc ¤Ë¥¨¥ó¥È¥ê¤òºîÀ®¤¹¤ëºÝ¤ËÀßÄꤷ¤¿¥Ý¥¤¥ó¥¿ ¤¬¤½¤Î¤Þ¤ÞÅϤµ¤ì¤Þ¤¹¡£¼ÂºÝ¤Ë¹Ô¤Ã¤Æ¤¤¤ëÆâÍƤ⡢Ä̾ï¤Î¥­¥ã¥é¥¯¥¿¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð ¤ÈÊѤï¤ê¤Þ¤»¤ó¡£

  • 88 ¡Á 112 ¹ÔÌÜ ( init_module )

    create_proc_entry ´Ø¿ô¤Ç¡¢/proc ¤Î²¼¤Ë¥¨¥ó¥È¥ê¤òºîÀ®¤·¤Æ¤¤¤Þ¤¹¡£

    #include <linux/proc_fs.h>
    struct proc_dir_entry* create_proc_entry( 
      const char* name, mode_t mode, struct proc_dir_entry* parent );
    
    

    name ¤Ë¤Ï¡¢/proc ¤Î²¼¤ËºîÀ®¤¹¤ë¥¨¥ó¥È¥ê̾¾Î¤ò»ØÄꤷ¤Þ¤¹¡£´û¤Ë¸ºß¤¹¤ë ¥¨¥ó¥È¥ê¤Î²¼¤ËºîÀ®¤¹¤ë¾ì¹ç¤Ï¡¢proc.c ¤Î "driver/sampleproc" ¤ÎÍͤ˳¬Áعþ¤ß¤Ç »ØÄꤹ¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£

    mode ¤Ë¤Ï¡¢ºîÀ®¤¹¤ë¥¨¥ó¥È¥ê¤Î¥Õ¥¡¥¤¥ë¼ïÊ̤äÆɤ߽ñ¤­¸¢¤ò»ØÄꤷ¤Þ¤¹¡£ ¤³¤ì¤é¤Ï¡¢linux/stat.h Æâ¤ÎÄê¿ô¤ò»ÈÍѤ·¤ÆÀßÄꤷ¤Þ¤¹¡£Äê¿ô¤Î°ÕÌ£¤Ï man stat ¤È¤¹¤ë¤ÈÂçÂÎʬ¤«¤ê¤Þ¤¹¡£Î㤨¤ÐÄ̾ï¤Î¥Õ¥¡¥¤¥ë¤Ç¡¢½êÍ­¼Ô ( root ) ¤Î¤ß¤Î Æɤ߽ñ¤­¸¢¤È¤¹¤ë¤Ë¤Ï¡¢mode ¤Ë S_IFREG | S_IRUSR | S_IWUSR ¤ò»ØÄꤷ¤Þ¤¹¡£

    linux/stat.h ¤Ë¤Ï¡¢__KERNEL__ ¥Þ¥¯¥í¤òÄêµÁ¤·¤¿»þ¤Î¤ßÍ­¸ú¤Ë¤Ê¤ëÄê¿ô¤¬¤¢¤ê¡¢ proc.c ¤Ç¤Ï¤½¤ì¤ò»ÈÍѤ·¤Æ¤¤¤Þ¤¹¡£S_IRUGO ¤Ï S_IRUSR | S_IRGRP | S_IROTH ¤ÈƱ¤¸°ÕÌ£¤Ç¡¢S_IWUGO ¤Ï S_IWUSR | S_IWGRP | S_IWOTH ¤ÈƱ¤¸°ÕÌ£¤Ç¤¹¡£

    create_proc_entry ¤Ï¡¢À®¸ù¤¹¤ë¤È struct proc_dir_entry ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤·¤Þ¤¹¡£ ¿³¬ÁؤΥ¨¥ó¥È¥ê¤òºîÀ®¤·¤¿¤¤¾ì¹ç¤Ï¡¢¿Æ¤«¤é½ç¤Ë¥¨¥ó¥È¥ê¤òºîÀ®¤·¡¢create_proc_entry ¤ÎºÇ¸å¤Î°ú¿ô¤Ë¿Æ¤Î¥¨¥ó¥È¥ê¤òÀßÄꤷ¤Þ¤¹¡£

    create_proc_entry ¤Ç NULL °Ê³°¤Î¥Ý¥¤¥ó¥¿¤¬Ê֤äÆÍ褿¤é¡¢ Æɤ߽Ф·¡¿½ñ¤­¹þ¤ß¥¢¥¯¥»¥¹¥Ï¥ó¥É¥é¤ò struct proc_dir_entry ¤Î read_proc / write_proc ¥á¥ó¥Ð¤ËÀßÄꤷ¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢/proc °Ê²¼¤Î¥¨¥ó¥È¥ê¤Ë ÂФ¹¤ë¥¢¥¯¥»¥¹¤¬Å¾Á÷¤µ¤ì¤Æ¤­¤Þ¤¹¡£

    Æɤ߽Ф·¡¿½ñ¤­¹þ¤ß¥¢¥¯¥»¥¹¥Ï¥ó¥É¥é¤ËÅϤ·¤¿¤¤¥Ç¡¼¥¿¤¬¤¢¤ë¾ì¹ç¤Ï¡¢ ¤³¤³¤Ç struct proc_dir_entry ¤Î data ¥á¥ó¥Ð¤Ë¥Ý¥¤¥ó¥¿¤òÀßÄꤷ¤Æ¤ª¤¯¤È ¥Ï¥ó¥É¥é¼Â¹Ô»þ¤Ë°ú¿ô¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡£

    #include <linux/proc_fs.h>
    struct proc_dir_entry* entry;
    int value;
    
    entry->read_proc  = read_function;
    entry->write_proc = write_function;
    entry->data = ( void* )( &value );
    
    
  • 115 ¡Á 124 ¹ÔÌÜ ( cleanup_module )

    cleanup_module ¤Ç¤Ï¡¢ºîÀ®¤·¤¿ /proc ¥¨¥ó¥È¥ê¤ò remove_proc_entry ¤Ë¤è¤Ã¤Æ ºï½ü¤·¤Æ¤¤¤Þ¤¹¡£

    #include <linux/proc_fs.h>
    void remove_proc_entry( const char* name, struct proc_dir_entry* parent );
    
    

°Ê¾å¤Ç proc.c ¤Î²òÀâ¤Ï½ª¤ï¤ê¤Ç¤¹¡£/proc ¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ï¡¢¥Ç¥Ð¥Ã¥°ÍѤˤÁ¤ç¤Ã¤È¤·¤¿ÆâÉô¾ðÊó¤òɽ¼¨¤µ¤»¤¿¤ê¡¢³°Éô¤«¤é´Êñ¤Ë¥Ñ¥é¥á¡¼¥¿¤òÀßÄꤷ¤¿¤ê¤¹¤ë¤Î¤Ë»È¤¨¤Æ¤È¤Æ¤âÊØÍø¤À¤È»×¤¤¤Þ¤¹¡£

Á°¤Î¥Ú¡¼¥¸¤Ø ¼¡¤Î¥Ú¡¼¥¸¤Ø