· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
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. ¸î°¡Áö ÆÁµé

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;


----
  • [1] ¼ýÀÚ´Â pid °ªÀ» ÀǹÌ
  • [2] À§ÀÇ ÇÔ¼öµé·Î ¸¸µé¾îÁø °Íµé - ÀϹÝÆÄÀÏ, ½Éº¼¸¯ ¸µÅ©, ÀåÄ¡³ëµå, µð·ºÅ丮



ID
Password
Join
It's a poor workman who blames his tools.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2005-03-02 15:36:03
Processing time 0.0138 sec