ºìÁªLinuxÃÅ»§
Linux°ïÖú

ʹÓà /proc ÎļþϵͳÀ´·ÃÎÊ Linux Äں˵ÄÄÚÈÝ

·¢²¼Ê±¼ä:2006-08-21 00:22:00À´Ô´:ºìÁª×÷Õß:hfh08
/proc ÎļþϵͳÊÇÒ»¸öÐéÄâÎļþϵͳ£¬Í¨¹ýËü¿ÉÒÔʹÓÃÒ»ÖÖеķ½·¨ÔÚ Linux® Äں˿ռäºÍÓû§¿Õ¼äÖ®¼ä½øÐÐͨÐÅ¡£ÔÚ /proc ÎļþϵͳÖУ¬ÎÒÃÇ¿ÉÒÔ½«¶ÔÐéÄâÎļþµÄ¶Áд×÷ΪÓëÄÚºËÖÐʵÌå½øÐÐͨÐŵÄÒ»ÖÖÊֶΣ¬µ«ÊÇÓëÆÕͨÎļþ²»Í¬µÄÊÇ£¬ÕâЩÐéÄâÎļþµÄÄÚÈݶ¼ÊǶ¯Ì¬´´½¨µÄ¡£±¾ÎÄ¶Ô /proc ÐéÄâÎļþϵͳ½øÐÐÁ˽éÉÜ£¬²¢Õ¹Ê¾ÁËËüµÄÓ÷¨¡£
×î³õ¿ª·¢ /proc ÎļþϵͳÊÇΪÁËÌṩÓйØϵͳÖнø³ÌµÄÐÅÏ¢¡£µ«ÊÇÓÉÓÚÕâ¸öÎļþϵͳ·Ç³£ÓÐÓã¬Òò´ËÄÚºËÖеĺܶàÔªËØÒ²¿ªÊ¼Ê¹ÓÃËüÀ´±¨¸æÐÅÏ¢£¬»òÆôÓö¯Ì¬ÔËÐÐʱÅäÖá£

/proc Îļþϵͳ°üº¬ÁËһЩĿ¼£¨ÓÃ×÷×éÖ¯ÐÅÏ¢µÄ·½Ê½£©ºÍÐéÄâÎļþ¡£ÐéÄâÎļþ¿ÉÒÔÏòÓû§³ÊÏÖÄÚºËÖеÄһЩÐÅÏ¢£¬Ò²¿ÉÒÔÓÃ×÷Ò»ÖÖ´ÓÓû§¿Õ¼äÏòÄں˷¢ËÍÐÅÏ¢µÄÊֶΡ£Êµ¼ÊÉÏÎÒÃDz¢²»»áͬʱÐèҪʵÏÖÕâÁ½µã£¬µ«ÊDZ¾ÎĽ«ÏòÄúչʾÈçºÎÅäÖÃÕâ¸öÎļþϵͳ½øÐÐÊäÈëºÍÊä³ö¡£

¾¡¹ÜÏñ±¾ÎÄÕâÑù¶ÌСµÄһƪÎÄÕÂÎÞ·¨Ïêϸ½éÉÜ /proc µÄËùÓÐÓ÷¨£¬µ«ÊÇËüÒÀÈ»¶ÔÕâÁ½ÖÖÓ÷¨½øÐÐÁËչʾ£¬´Ó¶ø¿ÉÒÔÈÃÎÒÃÇÌå»áһϠ/proc ÊǶàôǿ´ó¡£Çåµ¥ 1 ÊÇ¶Ô /proc Öв¿·ÖÔªËؽøÐÐÒ»´Î½»»¥²éѯµÄ½á¹û¡£ËüÏÔʾµÄÊÇ /proc ÎļþϵͳµÄ¸ùĿ¼ÖеÄÄÚÈÝ¡£×¢Ò⣬ÔÚ×ó±ßÊÇһϵÁÐÊý×Ö±àºÅµÄÎļþ¡£Ã¿¸öʵ¼ÊÉ϶¼ÊÇÒ»¸öĿ¼£¬±íʾϵͳÖеÄÒ»¸ö½ø³Ì¡£ÓÉÓÚÔÚ GNU/Linux Öд´½¨µÄµÚÒ»¸ö½ø³ÌÊÇ init ½ø³Ì£¬Òò´ËËüµÄ process-id Ϊ 1¡£È»ºó¶ÔÕâ¸öĿ¼ִÐÐÒ»¸ö ls ÃüÁÕâ»áÏÔʾºÜ¶àÎļþ¡£Ã¿¸öÎļþ¶¼ÌṩÁËÓйØÕâ¸öÌØÊâ½ø³ÌµÄÏêϸÐÅÏ¢¡£ÀýÈ磬Ҫ²é¿´ init µÄ command-line ÏîµÄÄÚÈÝ£¬Ö»Ðè¶Ô cmdline ÎļþÖ´ÐÐ cat ÃüÁî¡£

/proc ÖÐÁíÍâһЩÓÐȤµÄÎļþÓУºcpuinfo£¬Ëü±êʶÁË´¦ÀíÆ÷µÄÀàÐͺÍËٶȣ»pci£¬ÏÔʾÔÚ PCI ×ÜÏßÉÏÕÒµ½µÄÉ豸£»modules£¬±êʶÁ˵±Ç°¼ÓÔص½ÄÚºËÖеÄÄ£¿é¡£


Çåµ¥ 1. ¶Ô /proc µÄ½»»¥¹ý³Ì

[root@plato]# ls /proc
1 2040 2347 2874 474 fb mdstat sys
104 2061 2356 2930 9 filesystems meminfo sysrq-trigger
113 2073 2375 2933 acpi fs misc sysvipc
1375 21 2409 2934 buddyinfo ide modules tty
1395 2189 2445 2935 bus interrupts mounts uptime
1706 2201 2514 2938 cmdline iomem mtrr version
179 2211 2515 2947 cpuinfo ioports net vmstat
180 2223 2607 3 crypto irq partitions
181 2278 2608 3004 devices kallsyms pci
182 2291 2609 3008 diskstats kcore self
2 2301 263 3056 dma kmsg slabinfo
2015 2311 2805 394 driver loadavg stat
2019 2337 2821 4 execdomains locks swaps
[root@plato 1]# ls /proc/1
auxv cwd exe loginuid mem oom_adj root statm task
cmdline environ fd maps mounts oom_score stat status wchan
[root@plato]# cat /proc/1/cmdline
init [5]
[root@plato]#




Çåµ¥ 2 չʾÁË¶Ô /proc ÖеÄÒ»¸öÐéÄâÎļþ½øÐжÁдµÄ¹ý³Ì¡£Õâ¸öÀý×ÓÊ×Ïȼì²éÄÚºËµÄ TCP/IP Õ»ÖÐµÄ IP ת·¢µÄÄ¿Ç°ÉèÖã¬È»ºóÔÙÆôÓÃÕâÖÖ¹¦ÄÜ¡£


Çåµ¥ 2. ¶Ô /proc ½øÐжÁд£¨ÅäÖÃÄںˣ©

[root@plato]# cat /proc/sys/net/ipv4/ip_forward
0
[root@plato]# echo "1" > /proc/sys/net/ipv4/ip_forward
[root@plato]# cat /proc/sys/net/ipv4/ip_forward
1
[root@plato]#




ÁíÍ⣬ÎÒÃÇ»¹¿ÉÒÔʹÓà sysctl À´ÅäÖÃÕâЩÄÚºËÌõÄ¿¡£ÓйØÕâ¸öÎÊÌâµÄ¸ü¶àÐÅÏ¢£¬Çë²ÎÔÄ ²Î¿¼×ÊÁÏ Ò»½ÚµÄÄÚÈÝ¡£

˳±ã˵һÏ£¬/proc Îļþϵͳ²¢²»ÊÇ GNU/Linux ϵͳÖеÄΩһһ¸öÐéÄâÎļþϵͳ¡£ÔÚÕâÖÖϵͳÉÏ£¬sysfs ÊÇÒ»¸öÓë /proc ÀàËƵÄÎļþϵͳ£¬µ«ÊÇËüµÄ×éÖ¯¸üºÃ£¨´Ó /proc ÖÐѧϰÁ˺ܶà½Ìѵ£©¡£²»¹ý /proc ÒѾ­È·Á¢ÁË×Ô¼ºµÄµØ룬Òò´Ë¼´Ê¹ sysfs Óë /proc Ïà±ÈÓÐһЩÓŵ㣬/proc Ò²ÒÀÈ»»á´æÔÚ¡£»¹ÓÐÒ»¸ö debugfs Îļþϵͳ£¬²»¹ý£¨¹ËÃû˼Ò壩ËüÌṩµÄ¸ü¶àÊǵ÷ÊÔ½Ó¿Ú¡£debugfs µÄÒ»¸öÓŵãÊÇËü½«Ò»¸öÖµµ¼³ö¸øÓû§¿Õ¼ä·Ç³£¼òµ¥£¨Êµ¼ÊÉÏÕâ²»¹ýÊÇÒ»¸öµ÷ÓöøÒÑ£©¡£

ÄÚºËÄ£¿é¼ò½é

¿É¼ÓÔØÄÚºËÄ£¿é£¨LKM£©ÊÇÓÃÀ´Õ¹Ê¾ /proc ÎļþϵͳµÄÒ»ÖÖ¼òµ¥·½·¨£¬ÕâÊÇÒòΪÕâÊÇÒ»ÖÖÓÃÀ´¶¯Ì¬µØÏò Linux ÄÚºËÌí¼Ó»òɾ³ý´úÂëµÄз½·¨¡£LKM Ò²ÊÇ Linux ÄÚºËÖÐΪÉ豸Çý¶¯³ÌÐòºÍÎļþϵͳʹÓõÄÒ»ÖÖÁ÷ÐлúÖÆ¡£

Èç¹ûÄúÔø¾­ÖØбàÒë¹ý Linux Äںˣ¬¾Í¿ÉÄܻᷢÏÖÔÚÄں˵ÄÅäÖùý³ÌÖУ¬ÓкܶàÉ豸Çý¶¯³ÌÐòºÍÆäËûÄÚºËÔªËض¼±»±àÒë³ÉÁËÄ£¿é¡£Èç¹ûÒ»¸öÇý¶¯³ÌÐò±»Ö±½Ó±àÒëµ½ÁËÄÚºËÖУ¬ÄÇô¼´Ê¹Õâ¸öÇý¶¯³ÌÐòûÓÐÔËÐУ¬ËüµÄ´úÂëºÍ¾²Ì¬Êý¾ÝÒ²»áÕ¼¾ÝÒ»²¿·Ö¿Õ¼ä¡£µ«ÊÇÈç¹ûÕâ¸öÇý¶¯³ÌÐò±»±àÒë³ÉÒ»¸öÄ£¿é£¬¾ÍÖ»ÓÐÔÚÐèÒªÄÚ´æ²¢½«Æä¼ÓÔص½ÄÚºËʱ²Å»áÕæÕýÕ¼ÓÃÄÚ´æ¿Õ¼ä¡£ÓÐȤµÄÊÇ£¬¶ÔÓÚ LKM À´Ëµ£¬ÎÒÃDz»»á×¢Òâµ½ÓÐʲôÐÔÄÜ·½ÃæµÄ²îÒ죬Òò´ËÕâ¶ÔÓÚ´´½¨Ò»¸öÊÊÓ¦ÓÚ×Ô¼º»·¾³µÄÄÚºËÀ´ËµÊÇÒ»ÖÖ¹¦ÄÜÇ¿´óµÄÊֶΣ¬ÕâÑù¿ÉÒÔ¸ù¾Ý¿ÉÓÃÓ²¼þºÍÁ¬½ÓµÄÉ豸À´¼ÓÔضÔÓ¦µÄÄ£¿é¡£

ÏÂÃæÊÇÒ»¸ö¼òµ¥µÄ LKM£¬¿ÉÒÔ°ïÖúÄúÀí½âËüÓëÔÚ Linux ÄÚºËÖп´µ½µÄ±ê×¼£¨·Ç¶¯Ì¬¿É¼ÓÔصģ©´úÂëÖ®¼äµÄÇø±ð¡£Çåµ¥ 3 ¸ø³öÁËÒ»¸ö×î¼òµ¥µÄ LKM¡££¨¿ÉÒÔ´Ó±¾ÎÄµÄ ÏÂÔØ Ò»½ÚÖÐÏÂÔØÕâ¸ö´úÂ룩¡£

Çåµ¥ 3 °üÀ¨Á˱ØÐëµÄÄ£¿éÍ·£¨Ëü¶¨ÒåÁËÄ£¿éµÄ API¡¢ÀàÐͺͺ꣩¡£È»ºóʹÓà MODULE_LICENSE ¶¨ÒåÁËÕâ¸öÄ£¿éʹÓõÄÐí¿ÉÖ¤¡£´Ë´¦£¬ÎÒÃǶ¨ÒåµÄÊÇ GPL£¬´Ó¶ø·ÀÖ¹»áÎÛȾµ½Äںˡ£

Çåµ¥ 3 È»ºóÓÖ¶¨ÒåÁËÕâ¸öÄ£¿éµÄ init ºÍ cleanup º¯Êý¡£my_module_init º¯ÊýÊÇÔÚ¼ÓÔØÕâ¸öÄ£¿éʱ±»µ÷Óõģ¬ËüÓÃÀ´½øÐÐһЩ³õʼ»¯·½ÃæµÄ¹¤×÷¡£my_module_cleanup º¯ÊýÊÇÔÚжÔØÕâ¸öÄ£¿éʱ±»µ÷Óõģ¬ËüÓÃÀ´ÊÍ·ÅÄÚ´æ²¢Çå³ýÕâ¸öÄ£¿éµÄ×Ù¼£¡£×¢Òâ´Ë´¦ printk µÄÓ÷¨£ºÕâÊÇÄÚºËµÄ printf º¯Êý¡£KERN_INFO ·ûºÅÊÇÒ»¸ö×Ö·û´®£¬¿ÉÒÔÓÃÀ´¶Ô½øÈëÄں˻ػ·»º³åÇøµÄÐÅÏ¢½øÐйýÂË£¨·Ç³£ÀàËÆÓÚ syslog£©¡£

×îºó£¬Çåµ¥ 3 ʹÓà module_init ºÍ module_exit ºêÉùÃ÷ÁËÈë¿Úº¯ÊýºÍ³ö¿Úº¯Êý¡£ÕâÑùÎÒÃǾͿÉÒÔ°´ÕÕ×Ô¼ºµÄÒâÔ¸À´¶ÔÕâ¸öÄ£¿éµÄ init ºÍ cleanup º¯Êý½øÐÐÃüÃûÁË£¬²»¹ýÎÒÃÇ×îÖÕÒª¸æËßÄÚºËά»¤º¯Êý¾ÍÊÇÕâЩº¯Êý¡£


Çåµ¥ 3. Ò»¸ö¼òµ¥µÄµ«¿ÉÒÔÕý³£¹¤×÷µÄ LKM£¨simple-lkm.c£©

#include

/* Defines the license for this LKM */
MODULE_LICENSE("GPL");

/* Init function called on module entry */
int my_module_init( void )
{
printk(KERN_INFO "my_module_init called. Module is now loaded.\n");

return 0;
}

/* Cleanup function called on module exit */
void my_module_cleanup( void )
{
printk(KERN_INFO "my_module_cleanup called. Module is now unloaded.\n");

return;
}

/* Declare entry and exit functions */
module_init( my_module_init );
module_exit( my_module_cleanup );




Çåµ¥ 3 ¾¡¹Ü·Ç³£¼òµ¥£¬µ«ËüÈ´ÊÇÒ»¸öÕæÕýµÄ LKM¡£ÏÖÔÚÈÃÎÒÃǶÔÆä½øÐбàÒë²¢ÔÚÒ»¸ö 2.6 °æ±¾µÄÄÚºËÉϽøÐвâÊÔ¡£2.6 °æ±¾µÄÄÚºËΪÄÚºËÄ£¿éµÄ±àÒëÒýÈëÁËÒ»ÖÖз½·¨£¬ÎÒ·¢ÏÖÕâÖÖ·½·¨±ÈÔ­À´µÄ·½·¨¼òµ¥Á˺ܶࡣ¶ÔÓÚÎļþ simple-lkm.c£¬ÎÒÃÇ¿ÉÒÔ´´½¨Ò»¸ö makefile£¬ÆäΩһÄÚÈÝÈçÏ£º


obj-m += simple-lkm.o




Òª±àÒë LKM£¬ÇëʹÓà make ÃüÁÈçÇåµ¥ 4 Ëùʾ¡£


Çåµ¥ 4. ±àÒë LKM

[root@plato]# make -C /usr/src/linux-`uname -r` SUBDIRS=$PWD modules
make: Entering directory `/usr/src/linux-2.6.11'
CC [M] /root/projects/misc/module2.6/simple/simple-lkm.o
Building modules, stage 2.
MODPOST
CC /root/projects/misc/module2.6/simple/simple-lkm.mod.o
LD [M] /root/projects/misc/module2.6/simple/simple-lkm.ko
make: Leaving directory `/usr/src/linux-2.6.11'
[root@plato]#




½á¹û»áÉú³ÉÒ»¸ö simple-lkm.ko Îļþ¡£Õâ¸öеÄÃüÃûÔ¼¶¨¿ÉÒÔ°ïÖú½«ÕâЩÄں˶ÔÏó£¨LKM£©Óë±ê×¼¶ÔÏóÇø·Ö¿ªÀ´¡£ÏÖÔÚ¿ÉÒÔ¼ÓÔØ»òжÔØÕâ¸öÄ£¿éÁË£¬È»ºó¿ÉÒԲ鿴ËüµÄÊä³ö¡£Òª¼ÓÔØÕâ¸öÄ£¿é£¬ÇëʹÓà insmod ÃüÁ·´Ö®£¬ÒªÐ¶ÔØÕâ¸öÄ£¿é£¬ÇëʹÓà rmmod ÃüÁî¡£lsmod ¿ÉÒÔÏÔʾµ±Ç°¼ÓÔØµÄ LKM£¨²Î¼ûÇåµ¥ 5£©¡£


Çåµ¥ 5. ²åÈë¡¢¼ì²éºÍɾ³ý LKM

[root@plato]# insmod simple-lkm.ko
[root@plato]# lsmod
Module Size Used by
simple_lkm 1536 0
autofs4 26244 0
video 13956 0
button 5264 0
battery 7684 0
ac 3716 0
yenta_socket 18952 3
rsrc_nonstatic 9472 1 yenta_socket
uhci_hcd 32144 0
i2c_piix4 7824 0
dm_mod 56468 3
[root@plato]# rmmod simple-lkm
[root@plato]#




×¢Ò⣬Äں˵ÄÊä³ö½øµ½ÁËÄں˻ػ·»º³åÇøÖУ¬¶ø²»ÊÇ´òÓ¡µ½ stdout ÉÏ£¬ÕâÊÇÒòΪ stdout Êǽø³ÌÌØÓеĻ·¾³¡£Òª²é¿´Äں˻ػ·»º³åÇøÖеÄÏûÏ¢£¬¿ÉÒÔʹÓà dmesg ¹¤¾ß£¨»òÕßͨ¹ý /proc ±¾ÉíʹÓà cat /proc/kmsg ÃüÁ¡£Çåµ¥ 6 ¸ø³öÁË dmesg ÏÔʾµÄ×îºó¼¸ÌõÏûÏ¢¡£


Çåµ¥ 6. ²é¿´À´×Ô LKM µÄÄÚºËÊä³ö

[root@plato]# dmesg | tail -5
cs: IO port probe 0xa00-0xaff: clean.
eth0: Link is down
eth0: Link is up, running at 100Mbit half-duplex
my_module_init called. Module is now loaded.
my_module_cleanup called. Module is now unloaded.
[root@plato]#




¿ÉÒÔÔÚÄÚºËÊä³öÖп´µ½Õâ¸öÄ£¿éµÄÏûÏ¢¡£ÏÖÔÚÈÃÎÒÃÇÔÝʱÀ뿪Õâ¸ö¼òµ¥µÄÀý×Ó£¬À´¿´¼¸¸ö¿ÉÒÔÓÃÀ´¿ª·¢ÓÐÓà LKM µÄÄÚºË API¡£
ÎÄÕÂÆÀÂÛ

¹²ÓÐ 2 ÌõÆÀÂÛ

  1. hfh08 ÓÚ 2006-08-21 00:22:35·¢±í:

    ͨ¹ý /proc ÎļþϵͳʵÏֲƸ»·Ö·¢

    ÏÂÃæÊÇÒ»¸ö¿ÉÒÔÖ§³Ö¶ÁдµÄ LKM¡£Õâ¸ö¼òµ¥µÄ³ÌÐòÌṩÁËÒ»¸ö²Æ¸»Ìðµã·Ö·¢¡£ÔÚ¼ÓÔØÕâ¸öÄ£¿éÖ®ºó£¬Óû§¾Í¿ÉÒÔʹÓà echo ÃüÁîÏòÆäÖе¼ÈëÎı¾²Æ¸»£¬È»ºóÔÙʹÓà cat ÃüÁîÖðÒ»¶Á³ö¡£

    Çåµ¥ 9 ¸ø³öÁË»ù±¾µÄÄ£¿éº¯ÊýºÍ±äÁ¿¡£init º¯Êý£¨init_fortune_module£©¸ºÔðʹÓà vmalloc À´ÎªÕâ¸öµãÐĹ޷ÖÅä¿Õ¼ä£¬È»ºóʹÓà memset ½«ÆäÈ«²¿ÇåÁ㡣ʹÓÃËù·ÖÅä²¢ÒѾ­Çå¿ÕµÄ cookie_pot Äڴ棬ÎÒÃÇÔÚ /proc Öд´½¨ÁËÒ»¸ö proc_dir_entry Ï²¢½«Æä³ÆΪ fortune¡£µ± proc_entry ³É¹¦´´½¨Ö®ºó£¬¶Ô×Ô¼ºµÄ±¾µØ±äÁ¿ºÍ proc_entry ½á¹¹½øÐÐÁ˳õʼ»¯¡£ÎÒÃǼÓÔØÁË /proc read ºÍ write º¯Êý£¨ÈçÇåµ¥ 9 ºÍÇåµ¥ 10 Ëùʾ£©£¬²¢È·¶¨Õâ¸öÄ£¿éµÄËùÓÐÕß¡£cleanup º¯Êý¼òµ¥µØ´Ó /proc ÎļþϵͳÖÐɾ³ýÕâÒ»ÏȻºóÊÍ·Å cookie_pot ËùÕ¼¾ÝµÄÄÚ´æ¡£

    cookie_pot ÊÇÒ»¸ö¹Ì¶¨´óС£¨4KB£©µÄÒ³£¬ËüʹÓÃÁ½¸öË÷Òý½øÐйÜÀí¡£µÚÒ»¸öÊÇ cookie_index£¬±êʶÁËÒª½«ÏÂÒ»¸ö cookie дµ½ÄÄÀïÈ¥¡£±äÁ¿ next_fortune ±êʶÁËÏÂÒ»¸ö cookie Ó¦¸Ã´ÓÄÄÀï¶ÁÈ¡ÒÔ±ã½øÐÐÊä³ö¡£ÔÚËùÓÐµÄ fortune Ï¶ÁÈ¡Ö®ºó£¬ÎÒÃǼòµ¥µØ»Øµ½ÁË next_fortune¡£


    Çåµ¥ 9. Ä£¿éµÄ init/cleanup ºÍ±äÁ¿

    #include
    #include
    #include
    #include
    #include
    #include

    MODULE_LICENSE("GPL");
    MODULE_DESCRIPTION("Fortune Cookie Kernel Module");
    MODULE_AUTHOR("M. Tim Jones");

    #define MAX_COOKIE_LENGTH PAGE_SIZE
    static struct proc_dir_entry *proc_entry;

    static char *cookie_pot; // Space for fortune strings
    static int cookie_index; // Index to write next fortune
    static int next_fortune; // Index to read next fortune


    int init_fortune_module( void )
    {
    int ret = 0;

    cookie_pot = (char *)vmalloc( MAX_COOKIE_LENGTH );

    if (!cookie_pot) {
    ret = -ENOMEM;
    } else {

    memset( cookie_pot, 0, MAX_COOKIE_LENGTH );

    proc_entry = create_proc_entry( "fortune", 0644, NULL );

    if (proc_entry == NULL) {

    ret = -ENOMEM;
    vfree(cookie_pot);
    printk(KERN_INFO "fortune: Couldn't create proc entry\n");

    } else {

    cookie_index = 0;
    next_fortune = 0;

    proc_entry->read_proc = fortune_read;
    proc_entry->write_proc = fortune_write;
    proc_entry->owner = THIS_MODULE;
    printk(KERN_INFO "fortune: Module loaded.\n");

    }

    }

    return ret;
    }


    void cleanup_fortune_module( void )
    {
    remove_proc_entry("fortune", &proc_root);
    vfree(cookie_pot);
    printk(KERN_INFO "fortune: Module unloaded.\n");
    }


    module_init( init_fortune_module );
    module_exit( cleanup_fortune_module );




    ÏòÕâ¸ö¹ÞÖÐÐÂдÈëÒ»¸ö cookie ·Ç³£¼òµ¥£¨ÈçÇåµ¥ 10 Ëùʾ£©¡£Ê¹ÓÃÕâ¸öдÈë cookie µÄ³¤¶È£¬ÎÒÃÇ¿ÉÒÔ¼ì²éÊÇ·ñÓÐÕâô¶à¿Õ¼ä¿ÉÓá£Èç¹ûûÓУ¬¾Í·µ»Ø -ENOSPC£¬Ëü»á·µ»Ø¸øÓû§¿Õ¼ä¡£·ñÔò£¬¾Í˵Ã÷¿Õ¼ä´æÔÚ£¬ÎÒÃÇʹÓà copy_from_user ½«Óû§»º³åÇøÖеÄÊý¾ÝÖ±½Ó¿½±´µ½ cookie_pot ÖС£È»ºóÔö´ó cookie_index£¨»ùÓÚÓû§»º³åÇøµÄ³¤¶È£©²¢Ê¹Óà NULL À´½áÊøÕâ¸ö×Ö·û´®¡£×îºó£¬·µ»Øʵ¼ÊдÈë cookie_pot µÄ×Ö·ûµÄ¸öÊý£¬Ëü»á·µ»Øµ½Óû§½ø³Ì¡£


    Çåµ¥ 10. ¶Ô fortune ½øÐÐдÈë²Ù×÷ËùʹÓõĺ¯Êý

    ssize_t fortune_write( struct file *filp, const char __user *buff,
    unsigned long len, void *data )
    {
    int space_available = (MAX_COOKIE_LENGTH-cookie_index)+1;

    if (len > space_available) {

    printk(KERN_INFO "fortune: cookie pot is full!\n");
    return -ENOSPC;

    }

    if (copy_from_user( &cookie_pot[cookie_index], buff, len )) {
    return -EFAULT;
    }

    cookie_index += len;
    cookie_pot[cookie_index-1] = 0;

    return len;
    }




    ¶Ô fortune ½øÐжÁÈ¡Ò²·Ç³£¼òµ¥£¬ÈçÇåµ¥ 11 Ëùʾ¡£ÓÉÓÚÎÒÃǸղÅдÈëÊý¾ÝµÄ»º³åÇø£¨page£©ÒѾ­ÔÚÄں˿ռäÖÐÁË£¬Òò´Ë¿ÉÒÔÖ±½Ó¶ÔÆä½øÐвÙ×÷£¬²¢Ê¹Óà sprintf À´Ð´ÈëÏÂÒ»¸ö fortune¡£Èç¹û next_fortune Ë÷Òý´óÓÚ cookie_index£¨ÒªÐ´ÈëµÄÏÂÒ»¸öλÖã©£¬ÄÇôÎÒÃǾͽ« next_fortune ·µ»ØΪ 0£¬ÕâÊǵÚÒ»¸ö fortune µÄË÷Òý¡£ÔÚ½«Õâ¸ö fortune дÈëÓû§»º³åÇøÖ®ºó£¬ÔÚ next_fortune Ë÷ÒýÉÏÔö¼Ó¸Õ²ÅдÈëµÄ fortune µÄ³¤¶È¡£ÕâÑù¾Í±ä³ÉÁËÏÂÒ»¸ö¿ÉÓà fortune µÄË÷Òý¡£Õâ¸ö fortune µÄ³¤¶È»á±»·µ»Ø²¢´«µÝ¸øÓû§¡£


    Çåµ¥ 11. ¶Ô fortune ½øÐжÁÈ¡²Ù×÷ËùʹÓõĺ¯Êý

    int fortune_read( char *page, char **start, off_t off,
    int count, int *eof, void *data )
    {
    int len;

    if (off > 0) {
    *eof = 1;
    return 0;
    }

    /* Wrap-around */
    if (next_fortune >= cookie_index) next_fortune = 0;

    len = sprintf(page, "%s\n", &cookie_pot[next_fortune]);

    next_fortune += len;

    return len;
    }




    ´ÓÕâ¸ö¼òµ¥µÄÀý×ÓÖУ¬ÎÒÃÇ¿ÉÒÔ¿´³öͨ¹ý /proc ÎļþϵͳÓëÄں˽øÐÐͨÐÅʵ¼ÊÉÏÊǼþ·Ç³£¼òµ¥µÄÊÂÇé¡£ÏÖÔÚÈÃÎÒÃÇÀ´¿´Ò»ÏÂÕâ¸ö fortune Ä£¿éµÄÓ÷¨£¨²Î¼ûÇåµ¥ 12£©¡£


    Çåµ¥ 12. չʾ fortune cookie LKM µÄÓ÷¨

    [root@plato]# insmod fortune.ko
    [root@plato]# echo "Success is an individual proposition. Thomas Watson" > /proc/fortune
    [root@plato]# echo "If a man does his best, what else is there? Gen. Patton" > /proc/fortune
    [root@plato]# echo "Cats: All your base are belong to us. Zero Wing" > /proc/fortune
    [root@plato]# cat /proc/fortune
    Success is an individual proposition. Thomas Watson
    [root@plato]# cat /proc/fortune
    If a man does his best, what else is there? General Patton
    [root@plato]#




    /proc ÐéÄâÎļþϵͳ¿ÉÒԹ㷺µØÓÃÀ´±¨¸æÄں˵ÄÐÅÏ¢£¬Ò²¿ÉÒÔÓÃÀ´½øÐж¯Ì¬ÅäÖá£ÎÒÃǻᷢÏÖËü¶ÔÓÚÇý¶¯³ÌÐòºÍÄ£¿é±à³ÌÀ´Ëµ¶¼ÊǷdz£ÍêÕûµÄ¡£ÔÚÏÂÃæµÄ ²Î¿¼×ÊÁÏ ÖУ¬ÎÒÃÇ¿ÉÒÔѧϰµ½¸ü¶àÏà¹Ø֪ʶ¡£

  2. hfh08 ÓÚ 2006-08-21 00:22:13·¢±í:

    ¼¯³Éµ½ /proc ÎļþϵͳÖÐ

    Äں˳ÌÐòÔ±¿ÉÒÔʹÓõıê×¼ API£¬LKM ³ÌÐòÔ±Ò²¿ÉÒÔʹÓá£LKM ÉõÖÁ¿ÉÒÔµ¼³öÄÚºËʹÓõÄбäÁ¿ºÍº¯Êý¡£ÓÐ¹Ø API µÄÍêÕû½éÉÜÒѾ­³¬³öÁ˱¾Îĵķ¶Î§£¬Òò´ËÎÒÃÇÔÚÕâÀïÖ»ÊǼòµ¥µØ½éÉܺóÃæÔÚչʾһ¸ö¸üÓÐÓÃµÄ LKM ʱËùʹÓõļ¸¸öÔªËØ¡£

    ´´½¨²¢É¾³ý /proc Ïî

    ÒªÔÚ /proc ÎļþϵͳÖд´½¨Ò»¸öÐéÄâÎļþ£¬ÇëʹÓà create_proc_entry º¯Êý¡£Õâ¸öº¯Êý¿ÉÒÔ½ÓÊÕÒ»¸öÎļþÃû¡¢Ò»×éȨÏÞºÍÕâ¸öÎļþÔÚ /proc ÎļþϵͳÖгöÏÖµÄλÖá£create_proc_entry µÄ·µ»ØÖµÊÇÒ»¸ö proc_dir_entry Ö¸Õ루»òÕßΪ NULL£¬ËµÃ÷ÔÚ create ʱ·¢ÉúÁË´íÎ󣩡£È»ºó¾Í¿ÉÒÔʹÓÃÕâ¸ö·µ»ØµÄÖ¸ÕëÀ´ÅäÖÃÕâ¸öÐéÄâÎļþµÄÆäËû²ÎÊý£¬ÀýÈçÔÚ¶Ô¸ÃÎļþÖ´ÐжÁ²Ù×÷ʱӦ¸Ãµ÷Óõĺ¯Êý¡£create_proc_entry µÄÔ­ÐÍºÍ proc_dir_entry ½á¹¹ÖеÄÒ»²¿·ÖÈçÇåµ¥ 7 Ëùʾ¡£


    Çåµ¥ 7. ÓÃÀ´¹ÜÀí /proc ÎļþϵͳÏîµÄÔªËØ

    struct proc_dir_entry *create_proc_entry( const char *name, mode_t mode,
    struct proc_dir_entry *parent );

    struct proc_dir_entry {
    const char *name; // virtual file name
    mode_t mode; // mode permissions
    uid_t uid; // File's user id
    gid_t gid; // File's group id
    struct inode_operations *proc_iops; // Inode operations functions
    struct file_operations *proc_fops; // File operations functions
    struct proc_dir_entry *parent; // Parent directory
    ...
    read_proc_t *read_proc; // /proc read function
    write_proc_t *write_proc; // /proc write function
    void *data; // Pointer to private data
    atomic_t count; // use count
    ...
    };

    void remove_proc_entry( const char *name, struct proc_dir_entry *parent );




    ÉÔºóÎÒÃǾͿÉÒÔ¿´µ½ÈçºÎʹÓà read_proc ºÍ write_proc ÃüÁîÀ´²åÈë¶ÔÕâ¸öÐéÄâÎļþ½øÐжÁдµÄº¯Êý¡£

    Òª´Ó /proc ÖÐɾ³ýÒ»¸öÎļþ£¬¿ÉÒÔʹÓà remove_proc_entry º¯Êý¡£ÒªÊ¹ÓÃÕâ¸öº¯Êý£¬ÎÒÃÇÐèÒªÌṩÎļþÃû×Ö·û´®£¬ÒÔ¼°Õâ¸öÎļþÔÚ /proc ÎļþϵͳÖеÄλÖã¨parent£©¡£Õâ¸öº¯ÊýÔ­ÐÍÈçÇåµ¥ 7 Ëùʾ¡£

    parent ²ÎÊý¿ÉÒÔΪ NULL£¨±íʾ /proc ¸ùĿ¼£©£¬Ò²¿ÉÒÔÊǺܶàÆäËûÖµ£¬ÕâÈ¡¾öÓÚÎÒÃÇÏ£Íû½«Õâ¸öÎļþ·Åµ½Ê²Ã´µØ·½¡£±í 1 ÁгöÁË¿ÉÒÔʹÓõÄÆäËûһЩ¸¸ proc_dir_entry£¬ÒÔ¼°ËüÃÇÔÚÕâ¸öÎļþϵͳÖеÄλÖá£


    ±í 1. proc_dir_entry ¿ì½Ý±äÁ¿
    proc_dir_entry ÔÚÎļþϵͳÖеÄλÖÃ
    proc_root_fs /proc
    proc_net /proc/net
    proc_bus /proc/bus
    proc_root_driver /proc/driver


    »Øµ÷º¯Êý

    ÎÒÃÇ¿ÉÒÔʹÓà write_proc º¯ÊýÏò /proc ÖÐдÈëÒ»Ïî¡£Õâ¸öº¯ÊýµÄÔ­ÐÍÈçÏ£º


    int mod_write( struct file *filp, const char __user *buff,
    unsigned long len, void *data );




    filp ²ÎÊýʵ¼ÊÉÏÊÇÒ»¸ö´ò¿ªÎļþ½á¹¹£¨ÎÒÃÇ¿ÉÒÔºöÂÔÕâ¸ö²ÎÊý£©¡£buff ²ÎÊýÊÇ´«µÝ¸øÄúµÄ×Ö·û´®Êý¾Ý¡£»º³åÇøµØַʵ¼ÊÉÏÊÇÒ»¸öÓû§¿Õ¼äµÄ»º³åÇø£¬Òò´ËÎÒÃDz»ÄÜÖ±½Ó¶ÁÈ¡Ëü¡£len ²ÎÊý¶¨ÒåÁËÔÚ buff ÖÐÓжàÉÙÊý¾ÝÒª±»Ð´Èë¡£data ²ÎÊýÊÇÒ»¸öÖ¸Ïò˽ÓÐÊý¾ÝµÄÖ¸Õ루²Î¼û Çåµ¥ 7£©¡£ÔÚÕâ¸öÄ£¿éÖУ¬ÎÒÃÇÉùÃ÷ÁËÒ»¸öÕâÖÖÀàÐ͵ĺ¯ÊýÀ´´¦Àíµ½´ïµÄÊý¾Ý¡£

    Linux ÌṩÁËÒ»×é API À´ÔÚÓû§¿Õ¼äºÍÄں˿ռäÖ®¼äÒƶ¯Êý¾Ý¡£¶ÔÓÚ write_proc µÄÇé¿öÀ´Ëµ£¬ÎÒÃÇʹÓÃÁË copy_from_user º¯ÊýÀ´Î¬»¤Óû§¿Õ¼äµÄÊý¾Ý¡£

    ¶Á»Øµ÷º¯Êý

    ÎÒÃÇ¿ÉÒÔʹÓà read_proc º¯Êý´ÓÒ»¸ö /proc ÏîÖжÁÈ¡Êý¾Ý£¨´ÓÄں˿ռ䵽Óû§¿Õ¼ä£©¡£Õâ¸öº¯ÊýµÄÔ­ÐÍÈçÏ£º


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




    page ²ÎÊýÊÇÕâЩÊý¾ÝдÈëµ½µÄλÖã¬ÆäÖÐ count ¶¨ÒåÁË¿ÉÒÔдÈëµÄ×î´ó×Ö·ûÊý¡£ÔÚ·µ»Ø¶àÒ³Êý¾Ý£¨Í¨³£Ò»Ò³ÊÇ 4KB£©Ê±£¬ÎÒÃÇÐèҪʹÓà start ºÍ off ²ÎÊý¡£µ±ËùÓÐÊý¾ÝÈ«²¿Ð´ÈëÖ®ºó£¬¾ÍÐèÒªÉèÖà eof£¨Îļþ½áÊø²ÎÊý£©¡£Óë write ÀàËÆ£¬data ±íʾµÄÒ²ÊÇ˽ÓÐÊý¾Ý¡£´Ë´¦ÌṩµÄ page »º³åÇøÔÚÄں˿ռäÖС£Òò´Ë£¬ÎÒÃÇ¿ÉÒÔÖ±½ÓдÈ룬¶ø²»Óõ÷Óà copy_to_user¡£

    ÆäËûÓÐÓõĺ¯Êý

    ÎÒÃÇ»¹¿ÉÒÔʹÓà proc_mkdir¡¢symlinks ÒÔ¼° proc_symlink ÔÚ /proc ÎļþϵͳÖд´½¨Ä¿Â¼¡£¶ÔÓÚÖ»ÐèÒªÒ»¸ö read º¯ÊýµÄ¼òµ¥ /proc ÏîÀ´Ëµ£¬¿ÉÒÔʹÓà create_proc_read_entry£¬Õâ»á´´½¨Ò»¸ö /proc Ï²¢ÔÚÒ»¸öµ÷ÓÃÖÐ¶Ô read_proc º¯Êý½øÐгõʼ»¯¡£ÕâЩº¯ÊýµÄÔ­ÐÍÈçÇåµ¥ 8 Ëùʾ¡£


    Çåµ¥ 8. ÆäËûÓÐÓÃµÄ /proc º¯Êý

    /* Create a directory in the proc filesystem */
    struct proc_dir_entry *proc_mkdir( const char *name,
    struct proc_dir_entry *parent );

    /* Create a symlink in the proc filesystem */
    struct proc_dir_entry *proc_symlink( const char *name,
    struct proc_dir_entry *parent,
    const char *dest );

    /* Create a proc_dir_entry with a read_proc_t in one call */
    struct proc_dir_entry *create_proc_read_entry( const char *name,
    mode_t mode,
    struct proc_dir_entry *base,
    read_proc_t *read_proc,
    void *data );

    /* Copy buffer to user-space from kernel-space */
    unsigned long copy_to_user( void __user *to,
    const void *from,
    unsigned long n );

    /* Copy buffer to kernel-space from user-space */
    unsigned long copy_from_user( void *to,
    const void __user *from,
    unsigned long n );

    /* Allocate a 'virtually' contiguous block of memory */
    void *vmalloc( unsigned long size );

    /* Free a vmalloc'd block of memory */
    void vfree( void *addr );

    /* Export a symbol to the kernel (make it visible to the kernel) */
    EXPORT_SYMBOL( symbol );

    /* Export all symbols in a file to the kernel (declare before module.h) */
    EXPORT_SYMTAB