|
¡û ¤Ï¤¸¤á¤Ë
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 ¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ï¡¢¥Ç¥Ð¥Ã¥°ÍѤˤÁ¤ç¤Ã¤È¤·¤¿ÆâÉô¾ðÊó¤òɽ¼¨¤µ¤»¤¿¤ê¡¢³°Éô¤«¤é´Êñ¤Ë¥Ñ¥é¥á¡¼¥¿¤òÀßÄꤷ¤¿¤ê¤¹¤ë¤Î¤Ë»È¤¨¤Æ¤È¤Æ¤âÊØÍø¤À¤È»×¤¤¤Þ¤¹¡£