#title Linux Kernel Procfs Guide '''''Linux Kernel Procfs Guide''''' ÀúÀÚ: Eric (J.A.K.) Mouw (, Delft University of Technology, Faculty of Information Technology and Systems) ¹ø¿ª: ±è³²Çü (, ¼­¿ï½Ã¸³´ëÇб³ ÀΰøÁö´É¿¬±¸½Ç) ------------------------ [[TableOfContents]] == Preface == ÀÌ ¹®¼­¿¡¼­´Â ¸®´ª½º Ä¿³Î¿¡ Æ÷ÇÔµÈ proc ÆÄÀÏ ½Ã½ºÅÛÀ» »ç¿ëÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ ¼³¸íÇÑ´Ù. ÀÌ ¹®¼­°¡ ¾²¿©Áú ¼ö ÀÖµµ·Ï ¾ÆÀ̵ð¾î°¡ ¶°¿À¸¥ °ÍÀº #kernelnewbies IRC ä³Î¿¡¼­ (http://www.kernelnewbies.org Âü°í) Jeff Garzik ÀÌ procfs ÀÇ »ç¿ë¹ýÀ» ¼³¸íÇÏ°í Alexander Viro °¡ ¸®´ª½º Ä¿³Î ¸ÞÀϸµ ¸®½ºÆ®¿¡ ¿Ã¸° ±ÛÀ» ³ª¿¡°Ô º¸³»ÁÖ¾úÀ» ¶§ÀÌ´Ù. ³ª´Â ÀÌ µ¿±â¸¦ ¸¶·ÃÇØ ÁÖ¾ú´ø Jeff Garzik °ú Alexander Viro ¿¡°Ô °¨»çÇÏ°í, ¶ÇÇÑ !SelfDocbook (http://people.redhat.com/twaugh/docbook/selfdocbook) À» ÅëÇØ µµ¿òÀ» ÁÖ¾ú´ø Tim Waugh °ú ¹®¼­¸¦ È®ÀÎÇØ ÁÖ¾ú´ø Marc Joosen ¿¡°Ô °¨»çÀÇ ¸»À» ÀüÇÑ´Ù. ÀÌ ¹®¼­´Â Mobile Multi-media Communications (http://www.mmc.tudelft.nl) °ú Ubiquitous Communications (http://www.ubicom.tudelft.nl) ¿¡¼­ Áö¿ø¹ÞÀº LART computing board (http://www.lart.tudelft.nl) ¿¡¼­ Å×½ºÆ®ÇÏ°í ÀÛ¼ºµÇ¾ú´Ù. Erik == ¼Ò°³ == `/proc` ÆÄÀÏ ½Ã½ºÅÛ (procfs) Àº ¸®´ª½º Ä¿³Î ³»¿¡ Á¸ÀçÇϴ Ưº°ÇÑ ÆÄÀÏ ½Ã½ºÅÛÀÌ´Ù. ÀÌ°ÍÀº °¡»óÀÇ ÆÄÀÏ ½Ã½ºÅÛÀ¸·Î ½ÇÁ¦ ºí·Ï µð¹ÙÀ̽º¿¡ ¿¬°áµÇ¾î ÀÖ´Â °ÍÀÌ ¾Æ´Ï¶ó ¿ÀÁ÷ ¸Þ¸ð¸® »ó¿¡¸¸ Á¸ÀçÇÑ´Ù. procfs ³»ÀÇ ÆÄÀÏÀº »ç¿ëÀÚ °ø°£ÀÇ ÇÁ·Î±×·¥ÀÌ Ä¿³ÎÀÇ Æ¯Á¤ Á¤º¸¸¦ Àоî¿À°Å³ª ({{{/proc/[0-9]+/}}} [[FootNote(¼ýÀÚ´Â pid °ªÀ» ÀǹÌ)]] ¿¡¼­ ÇØ´ç ÇÁ·Î¼¼½ºÀÇ Á¤º¸¸¦ ¾Ë¾Æ³¾ ¼ö ÀÖ´Â °Íó·³), µð¹ö±ëÀÇ ¸ñÀûÀ¸·Î (`/proc/ksyms` ¿Í °°ÀÌ) »ç¿ëµÉ ¼ö ÀÖ´Ù. ÀÌ ¹®¼­¿¡¼­´Â ¸®´ª½º Ä¿³Î ³»ÀÇ proc ÆÄÀÏ ½Ã½ºÅÛÀÇ »ç¿ë ¹æ¹ý¿¡ ´ëÇØ ¼³¸íÇÑ´Ù. ¸ÕÀú proc ÆÄÀÏ ½Ã½ºÅÛ ³»ÀÇ ÆÄÀÏÀ» ´Ù·ç´Âµ¥ °ü·ÃµÈ ¸ðµç ÇÔ¼öµéÀ» ¼Ò°³Çϵµ·Ï ÇÑ´Ù. ±×¸®°í »ç¿ëÀÚ °ø°£ÀÇ ÇÁ·Î±×·¥°ú ¾î¶»°Ô Åë½ÅÇÏ´ÂÁö¸¦ ¼³¸íÇÏ°í, ¸î°¡Áö ÆÁµéÀ» ¼Ò°³ÇÑ ÈÄ¿¡ ¸¶Áö¸·À¸·Î´Â À̸¦ ÀÌ¿ëÇÑ ¿ÏÀüÇÑ ¿¹Á¦¸¦ Çϳª º¸À̵µ·Ï ÇÏ°Ú´Ù. `/proc/sys` ³»ÀÇ ÆÄÀϵéÀº ½Ã½ºÅÛÀÇ ¼³Á¤¿¡ °ü·ÃµÈ ÆÄÀÏÀÓ¿¡ ÁÖÀÇÇϱ⠹ٶõ´Ù: ÀÌ ÆÄÀϵéÀº proc ÆÄÀÏ ½Ã½ºÅÛ¿¡ ¼ÓÇÑ °ÍÀÌ ¾Æ´Ï°í Kernel API Book »óÀÇ ¿ÏÀüÈ÷ ´Ù¸¥ API µé¿¡ ÀÇÇØ °ü¸®µÈ´Ù. == Procfs ´Ù·ç±â == ÀÌ Àå¿¡¼­´Â procfs ¿¡ ÆÄÀÏ, ½Éº¼¸¯ ¸µÅ©, ÀåÄ¡ ³ëµå, µð·ºÅ丮 µîÀÇ ¿©·¯ Ä¿³Î ÄÄÆ÷³ÍÆ® µéÀ» »ý¼ºÇÏ°í Á¦°ÅÇÏ´Â ÇÔ¼öµéÀ» ¼³¸íÇÑ´Ù. ½ÃÀÛÇϱâ Àü¿¡ ÇÑ°¡Áö ÁÖÀÇÇÒ »çÇ×ÀÌ ÀÖ´Ù: ¸¸¾à procfs ÀÇ ÇÔ¼öµéÀ» »ç¿ëÇϱâ À§Çؼ­´Â ¿Ã¹Ù¸¥ Çì´õÆÄÀÏÀ» Æ÷ÇÔ½ÃÄÑ¾ß ÇÑ´Ù! ÄÚµåÀÇ ½ÃÀۺκп¡ ´ÙÀ½°ú °°Àº ºÎºÐÀÌ µé¾î¾ß ÇÒ °ÍÀÌ´Ù. {{{#!vim c #include }}} === ÀÏ¹Ý ÆÄÀÏ »ý¼ºÇϱâ === {{{#!vim c struct proc_dir_entry* create_proc_entry(const char* name, mode_t mode, struct proc_dir_entry* parent); }}} ÀÌ ÇÔ¼ö´Â ''parent'' ¶ó´Â µð·ºÅ丮 ¾È¿¡ ÆÄÀÏ ¸ðµå·Î ''mode'' ¸¦ °¡Áö´Â ''name'' À̶ó´Â À̸§ÀÇ ÀÏ¹Ý ÆÄÀÏ(regular file) À» »ý¼ºÇÑ´Ù. procfs ÀÇ °¡Àå »óÀ§¿¡ ÆÄÀÏÀ» »ý¼ºÇϱâ À§Çؼ­´Â ''parent'' ÀÚ¸®¿¡ `NULL` À» ³ÖÀ¸¸é µÈ´Ù. ¼º°ø½Ã ÇÔ¼öÀÇ ¸®ÅÏ°ªÀº »õ·Î »ý¼ºµÈ `struct proc_dir_entry` ÀÇ Æ÷ÀÎÅÍ°¡ µÇ¸ç, ½ÇÆнÿ¡´Â `NULL` ÀÌ µÈ´Ù. 3Àå ¿¡¼­´Â ÀÌ·¯ÇÑ ÆÄÀÏÀ» °¡Áö°í ÇÒ ¼ö ÀÖ´Â ÀϵéÀ» ¼³¸íÇÑ´Ù. ÇÑ°¡Áö Ưº°ÇÑ Á¡Àº ¿©·¯ °³ÀÇ µð·ºÅ丮¸¦ ³Ñ¾î¼­ ÆÄÀÏÀ» »ý¼ºÇÏ´Â °ÍÀ» Çã¿ëÇÑ´Ù´Â °ÍÀÌ´Ù. ¿¹¸¦ µé¾î, `create_proc_entry("drivers/via0/info")` ¿Í °°ÀÌ »ç¿ëÇÑ °æ¿ì `via0` ¶ó´Â µð·ºÅ丮°¡ ¾ø´Ù¸é 0755 ÀÇ ±ÇÇÑÀ¸·Î ÀÌ µð·ºÅ丮¸¦ »ý¼ºÇÏ°Ô µÈ´Ù. ¸¸¾à ¿ÀÁ÷ ÆÄÀÏÀ» Àб⸸ ÇÒ ¸ñÀûÀ̶ó¸é, 4.1 Àý¿¡¼­ ¼Ò°³ÇÒ `create_proc_read_entry` ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© »ý¼º°ú ÃʱâÈ­¸¦ Çѹø¿¡ ó¸®ÇÒ ¼ö ÀÖ´Ù. === ½Éº¼¸¯ ¸µÅ© »ý¼ºÇϱâ === {{{#!vim c struct proc_dir_entry* proc_symlink(const char* name, struct proc_dir_entry* parent, const char* dest); }}} ÀÌ ÇÔ¼ö´Â ''parent'' µð·ºÅ丮 ³»¿¡ ''name'' À¸·ÎºÎÅÍ ''dest'' ¸¦ °¡¸®Å°´Â ½Éº¼¸¯ ¸µÅ©¸¦ »ý¼ºÇÑ´Ù. ÀÌ°ÍÀº »ç¿ëÀÚ °ø°£¿¡¼­ÀÇ `ln -s dest name` ¸í·ÉÀ¸·Î »ý°¢ÇÒ ¼ö ÀÖ´Ù. === ÀåÄ¡ ³ëµå »ý¼ºÇϱâ === {{{#!vim c struct proc_dir_entry* proc_mknod(const char* name, mode_t mode, struct proc_dir_entry* parent, kdev_t rdev); }}} ÀÌ ÇÔ¼ö´Â ''parent'' µð·ºÅ丮 ³»¿¡ ÆÄÀÏ ¸ðµå·Î ''mode'' ¸¦ °¡Áö´Â ''name'' À̶ó´Â ÀåÄ¡ ³ëµå (device file) ¸¦ »ý¼ºÇÑ´Ù. ÀåÄ¡ ³ëµå´Â `linux/kdev_t.h` ³»ÀÇ `MKDEV` ¶ó´Â ¸ÅÅ©·Î¸¦ ÅëÇØ ¸¸µé¾îÁö´Â''rdev'' ¶ó´Â ÀåÄ¡¿Í ÇÔ²² µ¿ÀÛÇÒ °ÍÀÌ´Ù. ''mode'' ¿¡´Â ÀåÄ¡ ³ëµå¸¦ »ý¼ºÇϱâ À§ÇØ '''¹Ýµå½Ã''' `S_IFBLK` ³ª `S_IFCHR` ÁßÀÇ Çϳª¸¦ Æ÷ÇÔÇØ¾ß ÇÑ´Ù. ÀÌ°ÍÀº »ç¿ëÀÚ °ø°£¿¡¼­ÀÇ `mknod --mode=mode name rdev` ¸í·ÉÀ¸·Î »ý°¢ÇÒ ¼ö ÀÖ´Ù. === µð·ºÅ丮 »ý¼ºÇϱâ === {{{#!vim c struct proc_dir_entry* proc_mkdir(const char* name, struct proc_dir_entry* parent); }}} ÀÌ ÇÔ¼ö´Â ''parent'' µð·ºÅ丮 ¾È¿¡ ''name'' À̶ó´Â À̸§ÀÇ µð·ºÅ丮¸¦ »ý¼ºÇÑ´Ù. === ¿£Æ®¸® »èÁ¦Çϱâ === {{{#!vim c void remove_proc_entry(const char* name, struct proc_dir_entry* parent); }}} ÀÌ ÇÔ¼ö´Â procfs ³»ÀÇ ''parent'' µð·ºÅ丮 ¾È¿¡ ÀÖ´Â ''name'' À̶ó´Â À̸§ÀÇ ¿£Æ®¸® [[FootNote(À§ÀÇ ÇÔ¼öµé·Î ¸¸µé¾îÁø °Íµé - ÀϹÝÆÄÀÏ, ½Éº¼¸¯ ¸µÅ©, ÀåÄ¡³ëµå, µð·ºÅ丮)]] ¸¦ »èÁ¦ÇÑ´Ù. °¢ ¿£Æ®¸®´Â ''name'' À» ÅëÇØ »èÁ¦µÇ¸ç, °¢°¢ÀÇ »ý¼º ÇÔ¼öµéÀ» ÅëÇØ ¹ÝȯµÈ `proc_dir_entry` ±¸Á¶Ã¼·Î´Â Áö¿ï ¼ö ¾ø´Ù. ÇÑ°¡Áö ÁÖÀÇÇÒ »çÇ×Àº ÀÌ ÇÔ¼ö´Â Àç±ÍÀûÀ¸·Î ¿£Æ®¸®¸¦ »èÁ¦ÇÏÁö ¾Ê´Â´Ù´Â Á¡ÀÌ´Ù. ¸¸¾à ¿£Æ®¸®¿¡ °ü·ÃµÈ µ¥ÀÌŸ°¡ ÇÒ´çµÇ¾ú´Ù¸é, `remove_proc_entry` ÇÔ¼ö¸¦ È£ÃâÇϱâ Àü¿¡ µ¥ÀÌŸ¸¦ ÇØÁ¦ÇØ¾ß ÇÑ´Ù. 3.3 Àý¿¡¼­ ÀÌ·¯ÇÑ µ¥ÀÌŸ¸¦ »ç¿ëÇÏ´Â ¹ý¿¡ ´ëÇØ ´õ ÀÚ¼¼È÷ ¾Ë¾Æº¸°Ú´Ù. == »ç¿ëÀÚ °ø°£°ú Åë½ÅÇϱâ == procfs ¿¡¼­´Â Ä¿³ÎÀÇ ¸Þ¸ð¸®¸¦ Á÷Á¢ Á¢±ÙÇÏ¿© Á¤º¸¸¦ ¾ò¾î¿À´Â ´ë½Å¿¡ ÆÄÀÏÀÇ '''Äݹé ÇÔ¼ö''' ¸¦ ÅëÇØ µ¿ÀÛÇÑ´Ù: ÀÌ·¯ÇÑ ÇÔ¼öµéÀº ƯÁ¤ ÆÄÀÏÀ» Àаųª ¾µ ¶§ È£ÃâµÈ´Ù. À̸¦ ÀÌ¿ëÇϱâ À§Çؼ­´Â procfs ÀÇ ÆÄÀÏÀ» »ý¼ºÇÑ ÈÄ¿¡ `create_proc_entry` ÇÔ¼ö¸¦ ÅëÇØ ¹ÝȯµÈ `proc_dir_entry` ±¸Á¶Ã¼ÀÇ `read_proc` À̳ª `write_proc` µîÀÇ Çʵ带 ÃʱâÈ­ ÇØ ÁÖ¾î¾ß ÇÑ´Ù: {{{#!vim c struct proc_dir_entry* entry; entry->read_proc = read_proc_foo; entry->write_prpc = write_proc_foo; }}} ¸¸¾à `read_proc` ¸¸À» »ç¿ëÇÏ´Â °æ¿ì¶ó¸é, 4.1 Àý¿¡¼­ ¼Ò°³ÇÒ `create_proc_read_entry` ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¸é »ý¼º°ú ÃʱâÈ­¸¦ Çѹø¿¡ ¼öÇàÇÒ ¼ö ÀÖ´Ù. === µ¥ÀÌŸ Àбâ === read ÇÔ¼ö´Â »ç¿ëÀÚ °ø°£ÀÇ ÇÁ·Î¼¼½º°¡ Ä¿³Î ¿µ¿ªÀÇ µ¥ÀÌŸ¸¦ ÀÐÀ» ¼ö ÀÖµµ·Ï ÇØÁÖ´Â Äݹé ÇÔ¼öÀÌ´Ù. read ÇÔ¼ö´Â ´ÙÀ½°ú °°Àº ÇüÅ°¡ µÉ °ÍÀÌ´Ù: {{{#!vim c int read_func(char* page, char **start, off_t off, int count, int* eof, void* data); }}} read ÇÔ¼ö´Â Á¤º¸¸¦ Àоî¿Í¼­ ''page'' ¿¡ ÀúÀåÇÑ´Ù. ÀÌ ÇÔ¼ö¿¡¼­ ''off'' ´Â ''page'' ³»ÀÇ Á¤º¸¸¦ ±â·ÏÇÒ ½ÃÀÛÀ§Ä¡¸¦, ''count'' ·Î Àоî¿Ã ¹ÙÀÌÆ® ¼ö¸¦ ¸í½ÃÇÒ ¼ö ÀÖÁö¸¸, ´ëºÎºÐÀÇ read ÇÔ¼ö´Â ´Ü¼øÇÑ ÇüÅ°¡ µÇ°í, ¿ÀÁ÷ ÀûÀº ¾çÀÇ Á¤º¸ ¸¸À» ¹ÝȯÇϱ⠶§¹®¿¡ ÀϹÝÀûÀ¸·Î ÀÌ µÎ ÀÎÀÚ´Â ¹«½ÃµÈ´Ù. (ÀÌ°ÍÀº `more` ³ª `less` °°Àº ÆäÀÌÁö¸¦ Á¶ÀýÇÏ´Â ÇÁ·Î±×·¥À» ¹«½ÃÇÏ°Ô µÇÁö¸¸, `cat` Àº ¿©ÀüÈ÷ µ¿ÀÛÇÑ´Ù.) ¸¸¾à ''off'' ³ª ''count'' ÀÎÀÚ°¡ ÀûÀýÈ÷ »ç¿ëµÇ¸é, ''eof'' ÀÎÀÚ´Â ÆÄÀÏÀÇ ³¡ (End Of File) ¿¡ µµ´ÞÇß´ÂÁö¸¦ ³ªÅ¸³»´Â ½ÅÈ£·Î »ç¿ëµÉ °ÍÀÌ´Ù. (EOF ÀÎ °æ¿ì ''eof'' °¡ °¡¸®Å°´Â °÷ÀÇ °ªÀÌ 1·Î ¼³Á¤µÉ °ÍÀÌ´Ù.) ''start'' ÀÎÀÚ´Â Ä¿³Î³»ÀÇ ¾î´À °÷¿¡¼­µµ »ç¿ëµÇÁö ¾Ê´Â °ÍÀ¸·Î º¸ÀδÙ. ''data'' ÀÎÀÚ´Â ¿©·¯ ÆÄÀϵ鿡 ´ëÇÑ ÇϳªÀÇ Äݹé ÇÔ¼ö¸¦ »ý¼ºÇϴµ¥ ¾²ÀÏ ¼ö ÀÖ´Ù. - 3.3 Àý Âü°í `read_func` ´Â ¹Ýµå½Ã ''page'' ¿¡ ±â·ÏµÈ ¹ÙÀÌÆ® ¼ö¸¦ ¸®ÅÏÇØ¾ß ÇÑ´Ù. 5Àå¿¡¼­ read Äݹé ÇÔ¼ö°¡ ¾î¶»°Ô »ç¿ëµÇ´ÂÁö º¸°ÔµÉ °ÍÀÌ´Ù. === µ¥ÀÌŸ ¾²±â === write Äݹé ÇÔ¼ö´Â »ç¿ëÀÚ °ø°£ÀÇ ÇÁ·Î¼¼½º°¡ Ä¿³Î °ø°£¿¡ µ¥ÀÌŸ¸¦ ±â·ÏÇÒ ¼ö ÀÖµµ·Ï ÇØÁØ´Ù. µû¶ó¼­ ÀÌ ÇÔ¼ö´Â ÀÏÁ¾ÀÇ Ä¿³Î¿¡ ´ëÇÑ Á¦¾î±ÇÀ» °¡Áø´Ù. write ÇÔ¼ö´Â ´ÙÀ½°ú °°Àº ÇüÅ°¡ µÉ °ÍÀÌ´Ù: {{{#!vim c int write_func(struct file* file, const char* buffer, unsigned long count, void* data); }}} write ÇÔ¼ö´Â ''buffer'' ·Î ºÎÅÍ ÃÖ´ë ''count'' ¸¸Å­ÀÇ ¹ÙÀÌÆ®¸¦ ÀоîµéÀδÙ. ÁÖÀÇÇÒ »çÇ×Àº ''buffer'' ´Â Ä¿³Î ¸Þ¸ð¸® °ø°£¿¡ ¼ÓÇÑ °ÍÀÌ ¾Æ´Ï¶ó´Â °ÍÀÌ´Ù. µû¶ó¼­ ¸ÕÀú `copy_from_user` ¸¦ ÅëÇØ Ä¿³Î ¿µ¿ªÀ¸·Î µ¥ÀÌŸ¸¦ º¹»çÇØ¾ß ÇÑ´Ù. ''file'' ÀÎÀÚ´Â º¸Åë ¹«½ÃµÈ´Ù. 3.3 Àý¿¡¼­ ''data'' ÀÎÀÚ¸¦ ¾î¶»°Ô »ç¿ëÇÏ´ÂÁö¸¦ º¸¿©ÁØ´Ù. ´Ù½Ã ¸»ÇÏÁö¸¸, 5Àå¿¡¼­ ÀÌ ÄݹéÇÔ¼ö°¡ ¾î¶»°Ô »ç¿ëµÇ´ÂÁö º¸°Ô µÉ °ÍÀÌ´Ù. === ¿©·¯ ÆÄÀÏ¿¡¼­ ÇϳªÀÇ ÄݹéÇÔ¼ö ¾²±â === °ÅÀÇ ºñ½ÁÇÑ ÆÄÀÏÀÌ ¾ÆÁÖ ¸¹ÀÌ »ç¿ëµÉ ¶§, °¢°¢ÀÇ ÆÄÀÏ ¸¶´Ù °¢°¢ÀÇ Äݹé ÇÔ¼öµéÀ» »ç¿ëÇØ¾ß ÇÑ´Ù¸é ²Ï ºÒÆíÇÑ ÀÏÀÌµÉ °ÍÀÌ´Ù. À̸¦ À§ÇØ ÇϳªÀÇ Äݹé ÇÔ¼ö°¡ `struct proc_dir_entry` ÀÇ ''data'' Çʵ带 ÅëÇØ °¢°¢ÀÇ ÆÄÀϵéÀ» ±¸ºÐÇؼ­ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÇÏ°í ÀÖ´Ù. ¸ÕÀú ''data'' Çʵ尡 ÃʱâÈ­ µÇ¾î¾ß ÇÑ´Ù. {{{#!vim c struct proc_dir_entry* entry; struct my_file_data *file_data; file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL); entry->data = file_data; }}} ''data'' Çʵå´Â `void *` ÇüÀ̹ǷÎ, ¾î¶°ÇÑ ÇüÅ·εçÁö ÃʱâÈ­ µÉ ¼ö ÀÖ´Ù. ÀÌÁ¦ ''data'' Çʵ带 ¼³Á¤Çؼ­, `read_proc` °ú `write_proc` ÇÔ¼ö¿¡¼­ ÆÄÀϵéÀ» ±¸ºÐÇÒ ¼ö ÀÖ°Ô ÇÒ ¼ö ÀÖ´Ù. {{{#!vim c int foo_read_func(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; if(data == file_data) { /* special case for this file */ } else { /* normal processing */ } return len; } }}} procfs ÀÇ ¿£Æ®¸®¸¦ »èÁ¦ÇÒ ¶§ ''data'' Çʵ带 ÇØÁ¦ÇÏ´Â °ÍÀ» ÀØÁö¸»ÀÚ. == ¸î°¡Áö ÆÁµé == === Æí¸®ÇÑ ÇÔ¼ö === {{{#!vim c struct proc_dir_entry* create_proc_read_entry(const char* name, mode_t mode, struct proc_dir_entry* parent, read_proc_t* read_proc, void* data); }}} ÀÌ ÇÔ¼ö´Â 2.1 Àý¿¡¼­ ¼³¸íÇÑ `create_proc_entry` ¸¦ ÀÌ¿ëÇÑ °Í°ú ¿ÏÀüÈ÷ µ¿ÀÏÇÑ ¹æ½ÄÀ¸·Î ÀÏ¹Ý ÆÄÀÏÀ» »ý¼ºÇÏ°í ''read_proc'' À» ÅëÇØ read ÇÔ¼ö¸¦ ¼³Á¤ÇÑ´Ù. ÀÌ ÇÔ¼ö¿¡¼­µµ ¹°·Ð 3.3 Àý¿¡¼­ ¼³¸íÇÑ ''data'' ÀÎÀÚ¸¦ ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. === ¸ðµâ === ¸¸¾à procfs °¡ ¸ðµâ ³»¿¡¼­ »ç¿ëµÈ´Ù¸é, `struct proc_dir_entry` ³»ÀÇ ''owner'' Çʵ带 `THIS_MODULE` À̶ó´Â ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇØ ¼³Á¤ÇØ¾ß ÇÑ´Ù. {{{#!vim c struct proc_dir_entry* entry; entry->owner = THIS_MODULE; }}} === ÆÄÀÏ ¸ðµå¿Í ¼ÒÀ¯±Ç === ¶§¶§·Î procfs ¿£Æ®¸®ÀÇ ÆÄÀÏ ¸ðµå³ª ¼ÒÀ¯±ÇÀ» º¯È¯ÇØ¾ß ÇÒ ¶§°¡ ÀÖ´Ù. ÀÌ·¯ÇÑ °æ¿ìÀÇ ¿¹¸¦ ¾Æ·¡¿¡ º¸ÀδÙ: {{{#!vim c struct proc_dir_entry* entry; entry->mode = S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH; entry->uid = 0; entry->gid = 100; }}} == ¿¹Á¦ == {{{#!vim c /* * procfs_example.c: an example proc interface * * Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl) * * This file accompanies the procfs-guide in the Linux kernel * source. Its main use is to demonstrate the concepts and * functions described in the guide. * * This software has been developed while working on the LART * computing board (http://www.lart.tudelft.nl/), which is * sponsored by the Mobile Multi-media Communications * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications * (http://www.ubicom.tudelft.nl/) projects. * * The author can be reached at: * * Erik Mouw * Information and Communication Theory Group * Faculty of Information Technology and Systems * Delft University of Technology * P.O. Box 5031 * 2600 GA Delft * The Netherlands * * * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU General * Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #define MODULE_VERSION "1.0" #define MODULE_NAME "procfs_example" #define FOOBAR_LEN 8 struct fb_data_t { char name[FOOBAR_LEN + 1]; char value[FOOBAR_LEN + 1]; }; static struct proc_dir_entry *example_dir, *foo_file, *bar_file, *jiffies_file, *tty_device, *symlink; struct fb_data_t foo_data, bar_data; static int proc_read_jiffies(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; MOD_INC_USE_COUNT; len = sprintf(page, "jiffies = %ld\n", jiffies); MOD_DEC_USE_COUNT; return len; } static int proc_read_foobar(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; struct fb_data_t *fb_data = (struct fb_data_t *)data; MOD_INC_USE_COUNT; len = sprintf(page, "%s = '%s'\n", fb_data->name, fb_data->value); MOD_DEC_USE_COUNT; return len; } static int proc_write_foobar(struct file *file, const char *buffer, unsigned long count, void *data) { int len; struct fb_data_t *fb_data = (struct fb_data_t *)data; MOD_INC_USE_COUNT; if(count > FOOBAR_LEN) len = FOOBAR_LEN; else len = count; if(copy_from_user(fb_data->value, buffer, len)) { MOD_DEC_USE_COUNT; return -EFAULT; } fb_data->value[len] = '\0'; MOD_DEC_USE_COUNT; return len; } static int __init init_procfs_example(void) { int rv = 0; /* create directory */ example_dir = proc_mkdir(MODULE_NAME, NULL); if(example_dir == NULL) { rv = -ENOMEM; goto out; } example_dir->owner = THIS_MODULE; /* create jiffies using convenience function */ jiffies_file = create_proc_read_entry("jiffies", 0444, example_dir, proc_read_jiffies, NULL); if(jiffies_file == NULL) { rv = -ENOMEM; goto no_jiffies; } jiffies_file->owner = THIS_MODULE; /* create foo and bar files using same callback * functions */ foo_file = create_proc_entry("foo", 0644, example_dir); if(foo_file == NULL) { rv = -ENOMEM; goto no_foo; } strcpy(foo_data.name, "foo"); strcpy(foo_data.value, "foo"); foo_file->data = &foo_data; foo_file->read_proc = proc_read_foobar; foo_file->write_proc = proc_write_foobar; foo_file->owner = THIS_MODULE; bar_file = create_proc_entry("bar", 0644, example_dir); if(bar_file == NULL) { rv = -ENOMEM; goto no_bar; } strcpy(bar_data.name, "bar"); strcpy(bar_data.value, "bar"); bar_file->data = &bar_data; bar_file->read_proc = proc_read_foobar; bar_file->write_proc = proc_write_foobar; bar_file->owner = THIS_MODULE; /* create tty device */ tty_device = proc_mknod("tty", S_IFCHR | 0666, example_dir, MKDEV(5, 0)); if(tty_device == NULL) { rv = -ENOMEM; goto no_tty; } tty_device->owner = THIS_MODULE; /* create symlink */ symlink = proc_symlink("jiffies_too", example_dir, "jiffies"); if(symlink == NULL) { rv = -ENOMEM; goto no_symlink; } symlink->owner = THIS_MODULE; /* everything OK */ printk(KERN_INFO "%s %s initialised\n", MODULE_NAME, MODULE_VERSION); return 0; no_symlink: remove_proc_entry("tty", example_dir); no_tty: remove_proc_entry("bar", example_dir); no_bar: remove_proc_entry("foo", example_dir); no_foo: remove_proc_entry("jiffies", example_dir); no_jiffies: remove_proc_entry(MODULE_NAME, NULL); out: return rv; } static void __exit cleanup_procfs_example(void) { remove_proc_entry("jiffies_too", example_dir); remove_proc_entry("tty", example_dir); remove_proc_entry("bar", example_dir); remove_proc_entry("foo", example_dir); remove_proc_entry("jiffies", example_dir); remove_proc_entry(MODULE_NAME, NULL); printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERSION); } module_init(init_procfs_example); module_exit(cleanup_procfs_example); MODULE_AUTHOR("Erik Mouw"); MODULE_DESCRIPTION("procfs examples"); EXPORT_NO_SYMBOLS; }}} [[FootNote]] ---- CategoryDevelopment