Linux Kernel Procfs Guide
Linux Kernel Procfs Guide
ÀúÀÚ: Eric (J.A.K.) Mouw (<J.A.K.Mouw@its.tudelft.nl>, Delft University of Technology, Faculty of Information Technology and Systems)
¹ø¿ª: ±è³²Çü (<pastime@ece.uos.ac.kr>, ¼¿ï½Ã¸³´ëÇб³ ÀΰøÁö´É¿¬±¸½Ç)
1. Preface ¶ÀÌ ¹®¼¿¡¼´Â ¸®´ª½º Ä¿³Î¿¡ Æ÷ÇÔµÈ proc ÆÄÀÏ ½Ã½ºÅÛÀ» »ç¿ëÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ ¼³¸íÇÑ´Ù.
ÀÌ ¹®¼°¡ ¾²¿©Áú ¼ö ÀÖµµ·Ï ¾ÆÀ̵ð¾î°¡ ¶°¿À¸¥ °ÍÀº #kernelnewbies IRC ä³Î¿¡¼ (http://www.kernelnewbies.org Âü°í)
Jeff Garzik ÀÌ procfs ÀÇ »ç¿ë¹ýÀ» ¼³¸íÇÏ°í Alexander Viro °¡ ¸®´ª½º Ä¿³Î ¸ÞÀϸµ ¸®½ºÆ®¿¡ ¿Ã¸° ±ÛÀ» ³ª¿¡°Ô º¸³»ÁÖ¾úÀ» ¶§ÀÌ´Ù.
³ª´Â ÀÌ µ¿±â¸¦ ¸¶·ÃÇØ ÁÖ¾ú´ø Jeff Garzik <jgarzik@mandrakesoft.com> °ú Alexander Viro <viro@math.psu.edu> ¿¡°Ô °¨»çÇÏ°í,
¶ÇÇÑ SelfDocbook (http://people.redhat.com/twaugh/docbook/selfdocbook) À» ÅëÇØ µµ¿òÀ» ÁÖ¾ú´ø Tim Waugh <waugh@redhat.com> °ú
¹®¼¸¦ È®ÀÎÇØ ÁÖ¾ú´ø Marc Joosen <marcj@historia.et.tudelft.nl> ¿¡°Ô °¨»çÀÇ ¸»À» ÀüÇÑ´Ù.
ÀÌ ¹®¼´Â 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
2. ¼Ò°³ ¶/proc ÆÄÀÏ ½Ã½ºÅÛ (procfs) Àº ¸®´ª½º Ä¿³Î ³»¿¡ Á¸ÀçÇϴ Ưº°ÇÑ ÆÄÀÏ ½Ã½ºÅÛÀÌ´Ù.
ÀÌ°ÍÀº °¡»óÀÇ ÆÄÀÏ ½Ã½ºÅÛÀ¸·Î ½ÇÁ¦ ºí·Ï µð¹ÙÀ̽º¿¡ ¿¬°áµÇ¾î ÀÖ´Â °ÍÀÌ ¾Æ´Ï¶ó ¿ÀÁ÷ ¸Þ¸ð¸® »ó¿¡¸¸ Á¸ÀçÇÑ´Ù.
procfs ³»ÀÇ ÆÄÀÏÀº »ç¿ëÀÚ °ø°£ÀÇ ÇÁ·Î±×·¥ÀÌ Ä¿³ÎÀÇ Æ¯Á¤ Á¤º¸¸¦ Àоî¿À°Å³ª (/proc/[0-9]+/ [1] ¿¡¼
ÇØ´ç ÇÁ·Î¼¼½ºÀÇ Á¤º¸¸¦ ¾Ë¾Æ³¾ ¼ö ÀÖ´Â °Íó·³), µð¹ö±ëÀÇ ¸ñÀûÀ¸·Î (/proc/ksyms ¿Í °°ÀÌ) »ç¿ëµÉ ¼ö ÀÖ´Ù.
ÀÌ ¹®¼¿¡¼´Â ¸®´ª½º Ä¿³Î ³»ÀÇ proc ÆÄÀÏ ½Ã½ºÅÛÀÇ »ç¿ë ¹æ¹ý¿¡ ´ëÇØ ¼³¸íÇÑ´Ù.
¸ÕÀú proc ÆÄÀÏ ½Ã½ºÅÛ ³»ÀÇ ÆÄÀÏÀ» ´Ù·ç´Âµ¥ °ü·ÃµÈ ¸ðµç ÇÔ¼öµéÀ» ¼Ò°³Çϵµ·Ï ÇÑ´Ù.
±×¸®°í »ç¿ëÀÚ °ø°£ÀÇ ÇÁ·Î±×·¥°ú ¾î¶»°Ô Åë½ÅÇÏ´ÂÁö¸¦ ¼³¸íÇÏ°í, ¸î°¡Áö ÆÁµéÀ» ¼Ò°³ÇÑ ÈÄ¿¡
¸¶Áö¸·À¸·Î´Â À̸¦ ÀÌ¿ëÇÑ ¿ÏÀüÇÑ ¿¹Á¦¸¦ Çϳª º¸À̵µ·Ï ÇÏ°Ú´Ù.
/proc/sys ³»ÀÇ ÆÄÀϵéÀº ½Ã½ºÅÛÀÇ ¼³Á¤¿¡ °ü·ÃµÈ ÆÄÀÏÀÓ¿¡ ÁÖÀÇÇϱ⠹ٶõ´Ù:
ÀÌ ÆÄÀϵéÀº proc ÆÄÀÏ ½Ã½ºÅÛ¿¡ ¼ÓÇÑ °ÍÀÌ ¾Æ´Ï°í Kernel API Book »óÀÇ ¿ÏÀüÈ÷ ´Ù¸¥ API µé¿¡ ÀÇÇØ °ü¸®µÈ´Ù.
3. Procfs ´Ù·ç±â ¶ÀÌ Àå¿¡¼´Â procfs ¿¡ ÆÄÀÏ, ½Éº¼¸¯ ¸µÅ©, ÀåÄ¡ ³ëµå, µð·ºÅ丮 µîÀÇ ¿©·¯ Ä¿³Î ÄÄÆ÷³ÍÆ® µéÀ» »ý¼ºÇÏ°í Á¦°ÅÇÏ´Â ÇÔ¼öµéÀ» ¼³¸íÇÑ´Ù.
½ÃÀÛÇϱâ Àü¿¡ ÇÑ°¡Áö ÁÖÀÇÇÒ »çÇ×ÀÌ ÀÖ´Ù: ¸¸¾à procfs ÀÇ ÇÔ¼öµéÀ» »ç¿ëÇϱâ À§Çؼ´Â ¿Ã¹Ù¸¥ Çì´õÆÄÀÏÀ» Æ÷ÇÔ½ÃÄÑ¾ß ÇÑ´Ù!
ÄÚµåÀÇ ½ÃÀۺκп¡ ´ÙÀ½°ú °°Àº ºÎºÐÀÌ µé¾î¾ß ÇÒ °ÍÀÌ´Ù.
#include <linux/proc_fs.h>
3.1. ÀÏ¹Ý ÆÄÀÏ »ý¼ºÇϱ⠶
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 ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© »ý¼º°ú Ãʱâȸ¦ Çѹø¿¡ ó¸®ÇÒ ¼ö ÀÖ´Ù.
3.2. ½Éº¼¸¯ ¸µÅ© »ý¼ºÇϱ⠶
struct proc_dir_entry* proc_symlink(const char* name,
struct proc_dir_entry* parent, const char* dest); ÀÌ ÇÔ¼ö´Â parent µð·ºÅ丮 ³»¿¡ name À¸·ÎºÎÅÍ dest ¸¦ °¡¸®Å°´Â ½Éº¼¸¯ ¸µÅ©¸¦ »ý¼ºÇÑ´Ù.
ÀÌ°ÍÀº »ç¿ëÀÚ °ø°£¿¡¼ÀÇ
ln -s dest name ¸í·ÉÀ¸·Î »ý°¢ÇÒ ¼ö ÀÖ´Ù.
3.3. ÀåÄ¡ ³ëµå »ý¼ºÇϱ⠶
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 ¸í·ÉÀ¸·Î »ý°¢ÇÒ ¼ö ÀÖ´Ù.
3.4. µð·ºÅ丮 »ý¼ºÇϱ⠶
struct proc_dir_entry* proc_mkdir(const char* name,
struct proc_dir_entry* parent); ÀÌ ÇÔ¼ö´Â parent µð·ºÅ丮 ¾È¿¡ name À̶ó´Â À̸§ÀÇ µð·ºÅ丮¸¦ »ý¼ºÇÑ´Ù.
3.5. ¿£Æ®¸® »èÁ¦Çϱ⠶
void remove_proc_entry(const char* name, struct proc_dir_entry* parent);
ÀÌ ÇÔ¼ö´Â procfs ³»ÀÇ parent µð·ºÅ丮 ¾È¿¡ ÀÖ´Â name À̶ó´Â À̸§ÀÇ ¿£Æ®¸® [2]
¸¦ »èÁ¦ÇÑ´Ù. °¢ ¿£Æ®¸®´Â name À» ÅëÇØ »èÁ¦µÇ¸ç, °¢°¢ÀÇ »ý¼º ÇÔ¼öµéÀ» ÅëÇØ ¹ÝȯµÈ
proc_dir_entry ±¸Á¶Ã¼·Î´Â Áö¿ï ¼ö ¾ø´Ù.
ÇÑ°¡Áö ÁÖÀÇÇÒ »çÇ×Àº ÀÌ ÇÔ¼ö´Â Àç±ÍÀûÀ¸·Î ¿£Æ®¸®¸¦ »èÁ¦ÇÏÁö ¾Ê´Â´Ù´Â Á¡ÀÌ´Ù.
¸¸¾à ¿£Æ®¸®¿¡ °ü·ÃµÈ µ¥ÀÌŸ°¡ ÇÒ´çµÇ¾ú´Ù¸é,
remove_proc_entry ÇÔ¼ö¸¦ È£ÃâÇϱâ Àü¿¡ µ¥ÀÌŸ¸¦ ÇØÁ¦ÇØ¾ß ÇÑ´Ù.
3.3 Àý¿¡¼ ÀÌ·¯ÇÑ µ¥ÀÌŸ¸¦ »ç¿ëÇÏ´Â ¹ý¿¡ ´ëÇØ ´õ ÀÚ¼¼È÷ ¾Ë¾Æº¸°Ú´Ù.
4. »ç¿ëÀÚ °ø°£°ú Åë½ÅÇϱ⠶procfs ¿¡¼´Â Ä¿³ÎÀÇ ¸Þ¸ð¸®¸¦ Á÷Á¢ Á¢±ÙÇÏ¿© Á¤º¸¸¦ ¾ò¾î¿À´Â ´ë½Å¿¡ ÆÄÀÏÀÇ Äݹé ÇÔ¼ö ¸¦ ÅëÇØ µ¿ÀÛÇÑ´Ù:
ÀÌ·¯ÇÑ ÇÔ¼öµéÀº ƯÁ¤ ÆÄÀÏÀ» Àаųª ¾µ ¶§ È£ÃâµÈ´Ù.
À̸¦ ÀÌ¿ëÇϱâ À§Çؼ´Â procfs ÀÇ ÆÄÀÏÀ» »ý¼ºÇÑ ÈÄ¿¡
create_proc_entry ÇÔ¼ö¸¦ ÅëÇØ ¹ÝȯµÈ proc_dir_entry ±¸Á¶Ã¼ÀÇ
read_proc À̳ª write_proc µîÀÇ Çʵ带 ÃʱâÈ ÇØ ÁÖ¾î¾ß ÇÑ´Ù:
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 ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¸é »ý¼º°ú Ãʱâȸ¦ Çѹø¿¡ ¼öÇàÇÒ ¼ö ÀÖ´Ù.
4.1. µ¥ÀÌŸ Àб⠶read ÇÔ¼ö´Â »ç¿ëÀÚ °ø°£ÀÇ ÇÁ·Î¼¼½º°¡ Ä¿³Î ¿µ¿ªÀÇ µ¥ÀÌŸ¸¦ ÀÐÀ» ¼ö ÀÖµµ·Ï ÇØÁÖ´Â Äݹé ÇÔ¼öÀÌ´Ù.
read ÇÔ¼ö´Â ´ÙÀ½°ú °°Àº ÇüÅ°¡ µÉ °ÍÀÌ´Ù:
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 Äݹé ÇÔ¼ö°¡ ¾î¶»°Ô »ç¿ëµÇ´ÂÁö º¸°ÔµÉ °ÍÀÌ´Ù.
4.2. µ¥ÀÌŸ ¾²±â ¶write Äݹé ÇÔ¼ö´Â »ç¿ëÀÚ °ø°£ÀÇ ÇÁ·Î¼¼½º°¡ Ä¿³Î °ø°£¿¡ µ¥ÀÌŸ¸¦ ±â·ÏÇÒ ¼ö ÀÖµµ·Ï ÇØÁØ´Ù.
µû¶ó¼ ÀÌ ÇÔ¼ö´Â ÀÏÁ¾ÀÇ Ä¿³Î¿¡ ´ëÇÑ Á¦¾î±ÇÀ» °¡Áø´Ù.
write ÇÔ¼ö´Â ´ÙÀ½°ú °°Àº ÇüÅ°¡ µÉ °ÍÀÌ´Ù:
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Àå¿¡¼ ÀÌ ÄݹéÇÔ¼ö°¡ ¾î¶»°Ô »ç¿ëµÇ´ÂÁö º¸°Ô µÉ °ÍÀÌ´Ù.
4.3. ¿©·¯ ÆÄÀÏ¿¡¼ ÇϳªÀÇ ÄݹéÇÔ¼ö ¾²±â ¶°ÅÀÇ ºñ½ÁÇÑ ÆÄÀÏÀÌ ¾ÆÁÖ ¸¹ÀÌ »ç¿ëµÉ ¶§, °¢°¢ÀÇ ÆÄÀÏ ¸¶´Ù °¢°¢ÀÇ Äݹé ÇÔ¼öµéÀ» »ç¿ëÇØ¾ß ÇÑ´Ù¸é ²Ï ºÒÆíÇÑ ÀÏÀÌµÉ °ÍÀÌ´Ù.
À̸¦ À§ÇØ ÇϳªÀÇ Äݹé ÇÔ¼ö°¡
struct proc_dir_entry ÀÇ data Çʵ带 ÅëÇØ °¢°¢ÀÇ ÆÄÀϵéÀ» ±¸ºÐÇؼ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÇÏ°í ÀÖ´Ù.
¸ÕÀú data Çʵ尡 ÃʱâÈ µÇ¾î¾ß ÇÑ´Ù.
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 ÇÔ¼ö¿¡¼ ÆÄÀϵéÀ» ±¸ºÐÇÒ ¼ö ÀÖ°Ô ÇÒ ¼ö ÀÖ´Ù.
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 Çʵ带 ÇØÁ¦ÇÏ´Â °ÍÀ» ÀØÁö¸»ÀÚ.
5.1. Æí¸®ÇÑ ÇÔ¼ö ¶
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 ÀÎÀÚ¸¦ ¼³Á¤ÇÒ ¼ö ÀÖ´Ù.
5.2. ¸ðµâ ¶¸¸¾à procfs °¡ ¸ðµâ ³»¿¡¼ »ç¿ëµÈ´Ù¸é,
struct proc_dir_entry ³»ÀÇ owner Çʵ带 THIS_MODULE À̶ó´Â ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇØ ¼³Á¤ÇØ¾ß ÇÑ´Ù.
struct proc_dir_entry* entry;
entry->owner = THIS_MODULE; 5.3. ÆÄÀÏ ¸ðµå¿Í ¼ÒÀ¯±Ç ¶¶§¶§·Î procfs ¿£Æ®¸®ÀÇ ÆÄÀÏ ¸ðµå³ª ¼ÒÀ¯±ÇÀ» º¯È¯ÇØ¾ß ÇÒ ¶§°¡ ÀÖ´Ù. ÀÌ·¯ÇÑ °æ¿ìÀÇ ¿¹¸¦ ¾Æ·¡¿¡ º¸ÀδÙ:
struct proc_dir_entry* entry;
entry->mode = S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH; entry->uid = 0; entry->gid = 100; 6. ¿¹Á¦ ¶
/*
* 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 <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/sched.h> #include <asm/uaccess.h> #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; |
It's not reality that's important, but how you percieve things. |