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

LINUXÄÚºËÄ£¿é±à³Ì

·¢²¼Ê±¼ä:2006-11-09 01:07:58À´Ô´:ºìÁª×÷Õß:febspeolal
¡¶LinuxÄÚºËÇý¶¯Ä£¿é±à³ÌÖ¸ÄÏ¡·×î³õÊÇÓÉOri PomerantzΪ2.2°æ±¾µÄÄں˱àдµÄ £¬ºóÀ´£¬Ori½«ÎĵµÎ¬»¤µÄÈÎÎñ½»¸øÁËPeter Jay Salzman£¬PeterÍê³ÉÁË2.4Äں˰汾Îĵµ µÄ±àд£¬±Ï¾¹LinuxÄÚºËÇý¶¯Ä£¿éÊÇÒ»¸ö¸üкܿìµÄÄÚÈÝ¡£ÏÖÔÚ£¬PeterÒ²ÎÞ·¨ÌÚ³ö×ã¹»µÄ ʱ¼äÀ´Íê³É2.6Äں˰汾ÎĵµµÄ±àд£¬Ä¿Ç°¸Ã2.6Äں˰汾µÄÎĵµÓɺÏ×÷ÕßMichael Burian Íê³É¡£

°æ±¾ºÍ×¢Òâ
LinuxÄÚºËÄ£¿éÊÇÒ»¿é²»¶Ï¸üнø²½µÄÄÚÈÝ£¬ÔÚLKMPGÉÏ×ÜÓйØÓÚÊÇ·ñ±£Áô»¹ÊÇÀúÊ· °æ±¾µÄÕùÂÛ¡£MichaelºÍÎÒ×îÖÕÊǾö¶¨ÎªÃ¿¸öеÄÎȶ¨°æ±¾Äں˽¨Á¢Ò»¸öеÄÎĵµ·ÖÖ§¡£Ò² ¾ÍÊÇ˵LKMPG 2.4.xרעÓÚ2.4µÄÄںˣ¬¶øLKMPG 2.6.x½«×¨×¢ÓÚ2.6µÄÄںˡ£ÎÒÃDz»»áÔÚÒ» ƪÎĵµÖÐÌṩ¶Ô¾É°æ±¾Äں˵ÄÖ§³Ö£¬¶Ô´Ë¸ÐÐËȤµÄ¶ÁÕßÓ¦¸ÃÑ°ÕÒÏà¹Ø°æ±¾µÄÎĵµ·ÖÖ§¡£

ÔÚÎĵµÖеľø´ó²¿·ÖÔ´´úÂëºÍÌÖÂÛ¶¼Ó¦¸ÃÊÊÓÃÓÚÆäËüƽ̨£¬µ«ÎÒÎÞ·¨ÌṩÈκα£Ö¤¡£ÆäÖеÄÒ»¸öÀýÍâ¾ÍÊÇ Chapter 12, Öжϴ¦Àí¸ÃÕµÄÔ´´úÂëºÍÌÖÂÛ¾ÍÖ»ÊÊÓÃÓÚx86ƽ̨¡£

¸Ðл
¸ÐлÏÂÁÐÈËʿΪ´ËÎĵµÌṩÁËËûÃDZ¦¹óµÄÒâ¼û¡£ËûÃÇÊÇ£ºIgnacio Martin, David Porter, Daniele Paolo,Scarpazza ºÍ Dimo Velev¡£
ÒëÕß×¢
ÎÒ£¬ÒëÕߣ¬Ãû½ÐÌᄎ£¬Ä¿Ç°ÊÇÒ»ÃûÔÚ±±¾©Óʵç´óѧ¾Í¶ÁµÄͨÐÅרҵµÄ´óѧÉú¡£ ×Ô¸ßÖÐÆðÎÒ¾ÍÊÇLinuxµÄ°®ºÃÕß²¢×·ËæÖÁ½ñ¡£ÎÒϲ»¶Linux¸øÎÒ´øÀ´µÄ×ÔÓÉ£¬ÎÒÏë´ó¼ÒÒ²Ò»Ñù¡£Ã»ÓÐÈ˲»ÏòÍù×ÔÓÉ¡£

ÎÒѧϰÄÚºËÄ£¿é±àдʱ×î³õÔĶÁµÄÊÇOrelly³ö°æÉçµÄʹÓÃ2.0°æ±¾µÄÄں˵ÄÊé¼®£¬µ«ÈçͬÎÒÔ¤ÁϵÄÒ»Ñù£¬ ÊéÖеÄÐí¶àÊÂÀýÓÉÓÚÄں˴úÂëµÄ±ä»¯¶øÎÞ·¨Ê¹Óá£ÕâÈÃÏëÇ××ÔÌåÑéÄÚºËÄ£¿éµÄÉñÃصÄÎҷdz£¿àÄÕ¡£ ÎÒÔÚLinuxÎĵµ¼Æ»®ÔÚÉϺ£µÄ¾µÏñÕ¾ldp.linuxforum.netÉÏÕÒµ½ÁËÕâƪÎĵµ¡£

ÊÜÔ­×÷ÕßOriµÄ¹ÄÀø£¬»ùÓÚÉÏ´ÎÍê³ÉµÄLKMPG 2.4µÄ£¬ÄÚÈÝÓÐÉÔÐíµÄ¸Ä±äºÍÀ©³ä¡£Ó¦¸ÃÊÇÄ¿Ç°×îеÄÁË¡£ ·­ÒëµÄ·½Ê½ÓÐËù¸Ä±ä£¬ÔÚ»ùÓÚLDPÈϿɵÄdocbook¸ñʽÉÏ·­Ò룬ͨ¹ýdocbook2htmlת»»Îª¸½¼þÖеÄhtmlÎĵµ¡£ ÓÉÓÚ¶Ôdocbook²»ÊǺÜÊìϤ£¬ÆäÖеÄһЩ±êÌâÉÐδ·­Ò룬¶øÇÒ¿ÉÄÜÆÆ»µÁËÔ­ÓеÄtag£¬µ¼ÖÂhtml³öÏÖһЩ´íÎóÏÔʾ£¬ µ«×ÜÌåÀ´ËµºÜÉÙ¡£ÐÞ¸ÄÁ˺ܶà2.4ÖеĴí±ð×Ö¡£
ѧϰ²¢·ÖÏíѧϰµÄ¹ý³ÌÊÇÎÒ·­ÒëµÄ×îÖÕÄ¿µÄ¡£


Chapter 1. Introduction
Table of Contents
ʲôÊÇÄÚºËÄ£¿é£¿
ÄÚºËÄ£¿éÊÇÈçºÎ±»µ÷ÈëÄں˹¤×÷µÄ£¿
ʲôÊÇÄÚºËÄ£¿é£¿
ÏÖÔÚ£¬ÄãÊDz»ÊÇÏë±àдÄÚºËÄ£¿é¡£ÄãÓ¦¸Ã¶®µÃCÓïÑÔ£¬Ð´¹ýһЩÓû§³ÌÐò£¬ ÄÇôÏÖÔÚÄ㽫Ҫ¼ûʶһЩÕæʵµÄ¶«Î÷¡£ÔÚÕâÀÄã»á¿´µ½Ò»¸öÒ°ÂùµÄÖ¸ÕëÊÇÈçºÎ »ÙµôÄãµÄÎļþϵͳµÄ£¬Ò»´ÎÄں˱ÀÀ£Òâζ×ÅÖØÆô¶¯¡£

ʲôÊÇÄÚºËÄ£¿é£¿ÄÚºËÄ£¿éÊÇһЩ¿ÉÒÔÈòÙ×÷ϵͳÄÚºËÔÚÐèҪʱÔØÈëºÍÖ´ ÐеĴúÂ룬ÕâͬÑùÒâζ×ÅËü¿ÉÒÔÔÚ²»ÐèҪʱÓвÙ×÷ϵͳжÔØ¡£ËüÃÇÀ©Õ¹Á˲Ù×÷ϵ ͳÄں˵ŦÄÜÈ´²»ÐèÒªÖØÐÂÆô¶¯ÏµÍ³¡£¾ÙÀý×ÓÀ´Ëµ£¬ÆäÖÐÒ»ÖÖÄÚºËÄ£¿éʱÉ豸Çý ¶¯³ÌÐòÄ£¿é£¬ËüÃÇÓÃÀ´ÈòÙ×÷ϵͳÕýȷʶ±ð£¬Ê¹Óð²×°ÔÚϵͳÉϵÄÓ²¼þÉ豸¡£Èç ¹ûûÓÐÄÚºËÄ£¿é£¬ÎÒÃDz»µÃ²»Ò»´ÎÓÖÒ»´ÎÖØбàÒëÉú³Éµ¥Äں˲Ù×÷ϵͳµÄÄں˾µ ÏñÀ´¼ÓÈëÐµĹ¦ÄÜ¡£Õ⻹Òâζ×ÅÒ»¸öÓ·Ö×µÄÄںˡ£
ÄÚºËÄ£¿éÊÇÈçºÎ±»µ÷ÈëÄں˹¤×÷µÄ£¿
Äã¿ÉÒÔͨ¹ýÖ´ÐÐlsmodÃüÁîÀ´²é¿´ÄÚºËÒѾ­¼ÓÔØÁËÄÄ Ð©ÄÚºËÄ£¿é, ¸ÃÃüÁîͨ¹ý¶ÁÈ¡/proc/modulesÎļþµÄÄÚÈÝ À´»ñµÃËùÐèÐÅÏ¢¡£

ÕâЩÄÚºËÄ£¿éÊÇÈçºÎ±»µ÷ÈëÄں˵ģ¿µ±²Ù×÷ϵͳÄÚºËÐèÒªµÄÀ©Õ¹¹¦Äܲ»´æ ÔÚʱ£¬ÄÚºËÄ£¿é¹ÜÀíÊØ»¤½ø³Ìkmod[1]Ö´ÐÐmodprobeÈ¥¼ÓÔØÄÚºËÄ£ ¿é¡£Á½ÖÖÀàÐ͵IJÎÊý±»´«µÝ¸ømodprobe£º


Ò»¸öÄÚºËÄ£¿éµÄÃû×ÖÏñsoftdog»òÊÇppp¡£

ͨÓÃʶ±ð·ûÏñchar-major-10-30¡£

µ±´«µÝ¸ømodprobeÊÇͨÓÃʶ±ð·ûʱ£¬modprobeÊ×ÏÈÔÚÎļþ /etc/modules.conf²éÕÒ¸Ã×Ö·û´®¡£Èç¹ûËü·¢ÏÖµÄÒ»ÐбðÃûÏñ£º

alias char-major-10-30 softdog

Ëü¾ÍÃ÷°×ͨÓÃʶ±ð·ûÊÇÖ¸ÏòÄÚºËÄ£¿ésoftdog.o¡£

È»ºó£¬modprobe±éÀúÎļþ/lib/modules/version/modules.dep À´ÅжÏÊÇ·ñÓÐÆäËüÄÚºËÄ£¿éÐèÒªÔÚ¸ÃÄ£¿é¼ÓÔØÇ°±»¼ÓÔØ¡£¸ÃÎļþÊÇÓÉÃüÁîdepmod -a ½¨Á¢£¬±£´æ×ÅÄÚºËÄ£¿éµÄÒÀÀµ¹Øϵ¡£¾ÙÀýÀ´Ëµ£¬msdos.oÒÀÀµÓÚÄ£¿éfat.o ÄÚºËÄ£¿éÒѾ­±»ÄÚºËÔØÈë¡£µ±Òª¼ÓÔصÄÄÚºËÄ£¿éÐèҪʹÓñðµÄÄ£¿éÌṩµÄ·ûºÅÁ´½Óʱ£¨¶à°ëÊDZäÁ¿»òº¯Êý£©£¬ ÄÇôÄÇЩÌṩÕâЩËùÐè·ûºÅÁ´½ÓµÄÄÚºËÄ£¿é¾Í±»¸ÃÄ£¿éËùÒÀÀµ¡£

×îÖÕ£¬modprobeµ÷ÓÃinsmodÏȼÓÔر»ÒÀÀµµÄÄ£¿é£¬È»ºó¼ÓÔظñ»ÄÚºËÒªÇóµÄÄ£¿é¡£modprobe½«insmodÖ¸Ïò /lib/modules/version/[2]Ŀ¼£¬¸ÃĿ¼ΪĬÈϱê×¼´æ·ÅÄÚºËÄ£¿éµÄĿ¼¡£insmod¶ÔÄÚºËÄ£¿é´æ·ÅλÖà µÄ´¦ÀíÏ൱´ô°å£¬ËùÒÔmodprobeÓ¦¸ÃºÜÇå³þµÄÖªµÀĬÈϱê×¼µÄÄÚºËÄ£¿é´æ·ÅµÄλÖá£ËùÒÔ£¬µ±ÄãÏëÒªÔØÈëÒ»¸öÄÚ ºËÄ£¿éʱ£¬Äã¿ÉÒÔÖ´ÐУº

insmod /lib/modules/2.5.1/kernel/fs/fat/fat.o
insmod /lib/modules/2.5.1/kernel/fs/msdos/msdos.o

»òÖ»ÊÇÖ´ÐÐ"modprobe -a msdos"¡£

LinuxÌṩmodprobe, insmod and depmodÔÚÒ»¸öÃûΪmodutils »ò mod-utilsµÄ¹¤¾ß°üÄÚ¡£

ÔÚ½áÊø±¾ÕÂÇ°£¬ÈÃÎÒÃÇÀ´¿´Ò»¸ö /etc/modules.confÎļþ£º

#This file is automatically generated by update-modules
path[misc]=/lib/modules/2.4.?/local
keep
path[net]=~p/mymodules
options mydriver irq=10
alias eth0 eepro

ÓÃ'#'ÆðʼµÄÐÐΪעÊÍ¡£¿Õ°×Ðб»ºöÂÔ¡£

ÒÔ path[misc]ÆðʼµÄÐиæËßmodprobeÓà /lib/modules/2.4.?/localÌæ´úËÑÑ° miscÄÚºËÄ£¿éµÄ·¾¶¡£ÕýÈçÄã¿´µ½µÄ£¬ÃüÁî½âÊÍÆ÷shellµÄÔª×Ö·ûÒ²¿ÉÒÔʹÓá£

ÒÔpath[net]ÆðʼµÄÐиæËßmodprobe ÔÚĿ¼ ~p/mymodulesËÑË÷ÍøÂç·½ÃæµÄÄÚºËÄ£¿é¡£µ«ÊÇ£¬ÔÚpath[net] Ö¸Áî֮ǰʹÓõÄ"keep" Ö¸Áî¸æËßmodprobeÖ»Êǽ«¸Ã·¾¶Ìí¼Óµ½±ê×¼ËÑË÷·¾¶ÖУ¬¶ø²»ÊÇÏñ¶Ô´ý miscÇ°ÃæÄÇÑù½øÐÐÌæ»»¡£

ÒÔalias ÆðʼµÄµÄÐÐʹmodprobe¼ÓÔØeepro.oµ±kmod ÒÔͨÓÃʶ±ð·û'eth0' ÒªÇó¼ÓÔØÏàÓ¦ÄÚºËÄ£¿éʱ¡£

Äã²»»á·¢ÏÖÏñ"alias block-major-2 floppy"ÕâÑùµÄ±ðÃûÐÐÔÚÎļþ/etc/modules.conf ÒòΪmodprobeÒѾ­ÖªµÀÔÚ¾ø´ó¶àÊýϵͳÉÏ°²×°µÄ±ê×¼µÄÉ豸µÄÇý¶¯Ä£¿é¡£

ÏÖÔÚÄãÒѾ­ÖªµÀÄÚºËÄ£¿éÊÇÈçºÎ±»µ÷ÈëµÄÁË¡£µ±ÄãÏëдÄã×Ô¼ºµÄÒÀÀµÓÚÆäËüÄ£¿éµÄÄÚºËÄ£¿éʱ£¬ »¹ÓÐһЩÄÚÈÝûÓÐÌṩ¡£Õâ¸öÏà¶Ô¸ß¼¶µÄÎÊÌ⽫ÔÚÒÔºóµÄÕ½ÚÖнéÉÜ£¬µ±ÎÒÃÇÒѾ­Íê³ÉÇ°ÃæµÄѧϰºó¡£

ÔÚ¿ªÊ¼Ç°
ÔÚÎÒÃǽéÉÜÔ´´úÂëÇ°£¬ÓÐһЩÊÂÐèҪעÒ⡣ϵͳ±Ë´ËÖ®¼äµÄ²»Í¬»áµ¼ÖÂÐí¶àÀ§ÄÑ¡£ ˳ÀûµÄ±àÒë²¢ÇÒ¼ÓÔØÄãµÄµÚÒ»¸ö"hello world"Ä£¿éÓÐʱ¾Í»á±È½ÏÀ§ÄÑ¡£µ«Êǵ±Äã¿ç¹ý ÕâµÀ¿²Ê±£¬ºóÃæ»á˳ÀûµÄ¶à¡£

ÄÚºËÄ£¿éºÍÄں˵İ汾ÎÊÌâ
Ϊij¸ö°æ±¾±àÒëµÄÄ£¿é½«²»Äܱ»ÁíÒ»¸ö°æ±¾µÄÄں˼ÓÔØÈç¹ûÄÚºËÖдò¿ªÁË CONFIG_MODVERSIONSÑ¡Ïî¡£ÎÒÃÇÔÝʱ²»»áÌÖÂÛÓë´ËÏà¹ØµÄ ÄÚÈÝ¡£ÔÚÎÒÃǽøÈëÏà¹ØÄÚÈÝÇ°£¬±¾ÎĵµÖеķ¶Àý¿ÉÄÜÔÚ¸ÃÑ¡Ïî´ò¿ªµÄÇé¿öÏÂÎÞ·¨ ¹¤×÷¡£µ«ÊÇ£¬Ä¿Ç°¾ø´ó¶àÊýµÄ·¢ÐаæÊǽ«¸ÃÑ¡Ïî´ò¿ªµÄ¡£ËùÒÔÈç¹ûÄãÓöµ½ºÍ°æ±¾ Ïà¹ØµÄ´íÎóʱ£¬×îºÃ£¬ÖØбàÒëÒ»¸ö¹Ø±Õ¸ÃÑ¡ÏîµÄÄںˡ£

ʹÓà X´øÀ´µÄÎÊÌâ
Ç¿ÁÒ½¨ÒéÄãÔÚ¿ØÖÆ̨ÏÂÊäÈëÎĵµÖеķ¶Àý´úÂ룬±àÒëÈ»ºó¼ÓÔØÄ£¿é£¬¶ø²»ÊÇÔÚXÏ¡£

Ä£¿é²»ÄÜÏñprintf()ÄÇÑùÊä³öµ½ÆÁÄ»£¬µ«ËüÃÇ¿ÉÒÔ ¼Ç¼ÐÅÏ¢ºÍ¾¯¸æ£¬µ±ÇÒ½öµ±ÄãÔÚʹÓÿØÖÆ̨ʱÕâЩÐÅÏ¢²ÅÄÜ×îÖÕÏÔʾÔÚÆÁÄ»ÉÏ¡£ Èç¹ûÄã´ÓxtermÖÐinsmodÒ»¸öÄ£¿é£¬ÕâЩÈÕÖ¾ÐÅÏ¢Ö»»á¼Ç¼ÔÚÄãµÄÈÕÖ¾ÎļþÖС£ ³ýÁ˲鿴ÈÕÖ¾ÎļþÄ㽫ÎÞ·¨ µÃµ½Êä³öÐÅÏ¢¡£ÏëÒª¼°Ê±µÄ»ñµÃÕâЩÈÕÖ¾ÐÅÏ¢£¬½¨Òé ËùÓеŤ×÷¶¼ÔÚ¿ØÖÆ̨ϽøÐС£

±àÒëÏà¹ØºÍÄں˰汾Ïà¹ØµÄÎÊÌâ
LinuxµÄ·¢Ðа澭³£¸øÄں˴òһЩ·Ç±ê×¼µÄ²¹¶¡£¬ÕâÖÖÇé¿ö»Øµ¼ÖÂһЩÎÊÌâµÄ·¢Éú¡£

Ò»¸ö¸üÆÕ±éµÄÎÊÌâÊÇһЩLinux·¢ÐаæÌṩµÄÍ·Îļþ²»ÍêÕû¡£±àÒëÄ£¿éʱÄ㽫ÐèÒª·Ç³£¶à µÄÄÚºËÍ·Îļþ¡£Ä«·Æ·¨ÔòÖ®Ò»¾ÍÊÇÄÇЩȱÉÙµÄÍ·ÎļþÇ¡Ç¡ÊÇÄã×îÐèÒªµÄ¡£

ÎÒÇ¿ÁÒ½¨Òé´ÓLinux¾µÏñÕ¾µãÏÂÔØÔ´´úÂë°ü£¬±àÒëÐÂÄں˲¢ÓÃÐÂÄÚºËÆô¶¯ÏµÍ³À´±ÜÃâÒÔÉÏ µÄÎÊÌâ¡£²ÎÔÄ"Linux Kernel HOWTO"»ñµÃÏêϸÄÚÈÝ¡£

¾ßÓзí´ÌÒâζµÄÊÇ£¬ÕâÒ²»áµ¼ÖÂһЩÎÊÌâ¡£gccÇãÏòÓÚÔÚȱʡµÄÄÚºËÔ´Îļþ·¾¶(ͨ³£ÊÇ/usr/src/)ÏÂÑ°ÕÒÔ´´úÂëÎļþ¡£Õâ¿ÉÒÔͨ¹ýgccµÄ-I Ñ¡ÏîÀ´Çл»¡£

Notes
[1] ÔÚÔçÆÚµÄlinux°æ±¾ÖУ¬ÊÇ Ò»¸öÃûΪkerneldµÄÊØ»¤½ø³Ì¡£

[2] Èç¹ûÄãÔÚÐÞ¸ÄÄںˣ¬Îª±ÜÃâ ¸²¸ÇÄãÏÖÔÚ¹¤×÷µÄÄ£¿é£¬ÄãÓ¦¸ÃÊÔÊÔʹÓÃÄÚºËMakefileÖеıäÁ¿EXTRAVERSIONÈ¥½¨Á¢Ò»¸ö¶À Á¢µÄÄ£¿éĿ¼¡£
ÎÄÕÂÆÀÂÛ

¹²ÓÐ 17 ÌõÆÀÂÛ

  1. pengdejiu ÓÚ 2009-12-27 00:21:41·¢±í:

    Å££¬¿´²»¶®£¬¶¥Ò»¸ö

  2. masterlinux ÓÚ 2009-11-06 11:26:28·¢±í:

    ÒýÓÃ:
    ¶¥
    masterlinux ·¢±íÓÚ 2009-11-6 11:25

  3. masterlinux ÓÚ 2009-11-06 11:25:56·¢±í:

    ¶¥

  4. cxqcxq0177 ÓÚ 2006-12-12 10:24:54·¢±í:

    :0D1 £¬ÏÂÏÂÀ´¿´¿´

  5. febspeolal ÓÚ 2006-11-09 01:13:20·¢±í:

    Chapter 14. Common Pitfalls
    ×¢Òâ
    ÔÚÎÒÈÃÄãÃǽøÈëÄÚºËÄ£¿éµÄÊÀ½ç֮ǰ£¬ÎÒÐèÒªÌáÐÑÄãÃÇÏÂÃæµÄһЩעÒâ¡£Èç¹ûÎÒû¾¯¸æµ½ÄãÃǵ«ÊǵÄÈ··¢ÉúÁË£¬ ÄÇôÄ㽫ÎÊÌⱨ¸æÎÒ£¬ÎÒ½«È«¶îÍË»¹ÄãµÄÊé¿î¡£


    ʹÓñê×¼¿âÎļþ:
    ÄãÎÞ·¨ÕâÑù×ö¡£ÔÚÄÚºËÄ£¿éÖУ¬ÄãÖ»ÄÜʹÓÃÄÚºËÌṩµÄº¯Êý£¬Ò²¾ÍÊÇÄãÔÚ /proc/kallsymsÄܲ鵽µÄÄÇЩ¡£

    ½ûÓÃÖжÏ:
    ÄãÈç¹ûÕâÑù×öÁ˵«Ö»ÊÇһ˲¼ä£¬Ã»ÎÊÌ⣬µ±ÎÒûÌáÕâÊ¡£µ«ÊÇʺóÄãûÓлָ´ËüÃÇ£¬ Äã¾ÍÖ»ÄÜÞôµçÔ´¼üÀ´ÖØÆôÄ㽩ËÀµÄϵͳÁË¡£

    ³¢ÊÔһЩ·Ç³£Î£ÏյĶ«Î÷:
    ÕâÒ²Ðí²»Ó¦¸ÃÓÉÎÒÀ´Ëµ£¬µ«ÊÇÒÔ·ÀÍòÒ»£¬ÎÒ»¹ÊÇÌá³öÀ´°É£¡


    Appendix A. Changes: 2.0 To 2.2
    ´Ó2.0µ½2.2µÄ±ä»¯
    ´Ó2.0µ½2.2µÄ±ä»¯
    ÎÒ¶ÔÄں˵ÄÁ˽Ⲣ²»ºÜÍêÈ«ËùÒÔÎÒÒ²ÎÞ·¨Ð´³öËùÓеı仯¡£ÔÚÐ޸ĴúÂë £¨¸üÈ·ÇеÄ˵£¬ÊDzÉÓÃEmmanuel PapirakisµÄÐ޸ģ©Ê±£¬ÎÒÓöµ½ÁËÒÔϵÄÕâЩÐ޸ġ£ ÎÒ½«ËüÃǶ¼ÁгöÀ´ÒÔ·½±ãÄ£¿é±àдÕßÃÇ£¬ÌرðÊÇѧϰ¸Ãµµ°¸ÏÈÇ°°æ±¾²¢ÊìϤÎÒÌáµ½µÄÕâЩ¼¼ÇÉ £¨µ«ÒѾ­¸ü»»µ½Ð°汾µÄ£©µÄÄÇЩÈË¡£

    ¸ü¶àµÄÕâ·½ÃæµÄ²Î¿¼×ÊÁÏÔÚ Richard Gooch'sµÄÕ¾µãÉÏ¡£


    asm/uaccess.h
    Èç¹ûÄãҪʹÓÃput_user»òget_userÄã¾ÍÐèÒª #includeËü¡£

    get_user
    ÔÚ2.2°æ±¾ÖУ¬get_userͬʱ½ÓÊÕÓû§ÄÚ´æµÄÖ¸ÕëºÍÓÃÀ´ ÉèÖÃÐÅÏ¢µÄÄÚºËÄÚ´æÖбäÁ¿µÄÄÚ´æÖ¸Õë¡£±ä»¯µÄÔ­ÒòÊÇÒòΪµ±ÎÒÃǶÁÈ¡µÄ±äÁ¿ÊǶþ»òËĸö×Ö½Ú³¤µÄʱºò£¬ get_userÒ²¿ÉÒÔ¶ÁÈ¡¶þ»òËĸö×Ö½Ú³¤µÄ±äÁ¿¡£

    file_operations
    ¸Ä½á¹¹ÌåÏÖÔÚÓÐÁËÒ»¸ö¿ÉÒÔÔÚopenºÍ closeÖ®¼ä½øÐеÄˢвÙ×÷º¯Êý¡£

    close in file_operations
    2.2°æ±¾ÖУ¬close·µ»ØÕûÐÎÖµ£¬ËùÒÔ¿ÉÒÔ¼ì²âÊÇ·ñʧ°Ü¡£

    read,write in file_operations
    ÕâЩº¯ÊýµÄÍ·Îļþ¸Ä±äÁË¡£ËüÃÇÏÖÔÚ·µ»Øssize_t¶ø²»ÊÇÕûÐÎÖµ£¬ ÇÒËüÃǵIJÎÊý±íÒ²±äÁË¡£inode ²»ÔÙÊÇÒ»¸ö²ÎÊý£¬ÎļþÖеÄÆ«ÒÆÁ¿Ò²Ò»Ñù¡£

    proc_register_dynamic
    ¸Ãº¯ÊýÒѾ­²»¸´´æÔÚ¡£ÄãÓ¦¸ÃʹÓÃÓÃ0×÷Ϊinode²ÎÊýµÄproc_register º¯ÊýÀ´Ìæ´úËü¡£

    Signals
    ÔÚ task ½á¹¹ÌåÖеÄsignals²»ÔÙÊÇÒ»¸ö32λÕûÐαäÁ¿£¬¶øÊÇÒ»¸öΪ _NSIG_WORDS ÕûÐεÄÊý×é¡£

    queue_task_irq
    ¼´Ê¹ÄãÏëÔÚÖжϴ¦ÀíÄÚ²¿µ÷¶ÈÒ»¸öÈÎÎñ£¬ÄãÒ²Ó¦¸ÃʹÓà queue_task¶ø²»ÊÇqueue_task_irq¡£

    Module Parameters
    Äã²»±ØÔÚ½«Ä£¿é²ÎÊýÉùÃ÷Ϊȫ¾Ö±äÁ¿¡£ÔÚ2.2ÖУ¬Ê¹Óà MODULE_PARMÈ¥ÉùÃ÷Ä£¿é²ÎÊý¡£ÕâÊÇÒ»¸ö½ø²½£¬ ÕâÑù¾ÍÔÊÐíÄ£¿é½ÓÊÜÒÔÊý×Ö¿ªÍ·µÄ²ÎÊýÃû¶ø²»»á±»ÅªºýÍ¿¡£

    Symmetrical Multi-Processing
    Äں˱¾Ê¡ÒѲ»ÔÙÊÇÒ»¸öspinlock£¬Òâζ×ÅÄãµÄÄ£¿éÒ²Ó¦¸Ã¿¼ÂÇ SMPµÄÎÊÌâ¡£



    Appendix B. Where To Go From Here
    ΪʲôÕâÑùд£¿
    ÎÒÆäʵ¿ÉÒÔ¸øÕâ±¾ÊéÔÙ¼ÓÈ뼸Õ£¬ÀýÈçÈçºÎΪʵÏÖеÄÎļþϵͳ¼ÓÉÏÒ»Õ£¬»òÊÇÌí¼ÓÒ»¸öеÄЭÒéÕ»£¨Èç¹ûÓÐÕâÑùµÄ±ØÒªµÄ»°£¬ ÏëÕÒµ½Linux²»Ö§³ÖµÄÍøÂçЭÒéÒѾ­ÊǷdz£µÄÀ§ÄѵÄÁË£©¡£ÎÒ»¹¿ÉÒÔ½âÊÍÒ»ÏÂÎÒÃÇÉÐδ½Ó´¥µ½µÄÄÚºËʵÏÖ»úÖÆ£¬ÏñϵͳµÄÒýµ¼×Ô¾Ù£¬ »ò´ÅÅÌ´æ´¢¡£

    µ«ÊÇ£¬ÎÒ¾ö¶¨·ñ¡£ÎÒд±¾ÊéµÄÄ¿µÄÊÇÌṩ»ù±¾µÄ£¬ÈëÃŵĶÔÉñÃصÄÄÚºËÄ£¿é±à³ÌµÄÈÏʶºÍÕâ·½ÃæµÄ³£Óü¼ÇÉ¡£ ¶ÔÓÚÄÇЩ·Ç³£ÈÈÖÔÓëÄں˱à³ÌµÄÈË£¬ÎÒÍƼöJuan-Mariano de GoyenecheµÄ ÄÚºË×ÊÔ´ÁÐ±í ¡£ ͬÑù£¬¾ÍͬLinus±¾ÈË˵µÄÄÇÑù£¬Ñ§Ï°ÄÚºË×îºÃµÄ·½·¨ÊÇ×Ô¼ºÔĶÁÄÚºËÔ´´úÂë¡£

    Èç¹ûÄã¶Ô¸ü¶àµÄ¶ÌСµÄʾÀýÄÚºËÄ£¿é¸ÐÐËȤ£¬ÎÒÏòÄãÍƼö Phrack magazine Õâ±¾ÔÓÖ¾¡£ ¼´Ê¹Äã²»¹ØÐÄ°²È«ÎÊÌ⣬×÷Ϊһ¸ö³ÌÐòÔ±Ä㻹ÊÇÓ¦¸Ãʱʱ¿¼ÂÇÕâ¸öÎÊÌâµÄ¡£ÕâЩÄÚºËÄ£¿é´úÂ붼ºÜ¶Ì£¬²»ÐèÒª·Ñ¶à´ó¾¢¾ÍÄܶÁ¶®¡£

    ÎÒÏ£ÍûÎÒÂú×ãÁËÄãÏ£Íû³ÉΪһ¸ö¸üÓÅÐãµÄ³ÌÐòÔ±µÄÒªÇó£¬ÖÁÉÙÔÚѧϰ¼¼ÊõµÄ¹ý³ÌÖÐÌå»áµ½ÁËÀÖȤ¡£ Èç¹ûÄãÕæµÄдÁËһЩ·Ç³£ÓÐÓõÄÄ£¿é£¬ÎÒÏ£ÍûÄãʹÓÃGPLÐí¿ÉÖ¤·¢²¼ÄãµÄÄ£¿é£¬ÕâÑùÎÒÒ²¾Í¿ÉÒÔʹÓÃËüÃÇÁË¡£

  6. febspeolal ÓÚ 2006-11-09 01:12:49·¢±í:

    Chapter 13. Symmetric Multi Processing
    ¶Ô³Æ¶àÏ̴߳¦Àí
    Ìá¸ßÐÔÄܵÄ×î¼òµ¥Ò²ÊÇ×î±ãÒ˵ķ½·¨ÊǸøÄãµÄÖ÷°å¼ÓµÚ¶þ¸öCPU£¨Èç¹ûÄãµÄÖ÷°åÖ§³ÖµÄ»°£©¡£ Õâ¿ÉÒÔͨ¹ýÈò»Í¬µÄCPUÍê³É²»Í¬µÄ¹¤×÷£¨·Ç¶Ô³Æ¶àÏ̴߳¦Àí£©»òÊÇÏàͬµÄ¹¤×÷£¨¶Ô³Æ¶àÏ̴߳¦Àí£©¡£ ʵÏÖ¸ßЧÂʵķǶԳƵĶàÏ̴߳¦ÀíÐèÒªÌØÊâÓ²¼þÏà¹ØµÄ֪ʶ£¬¶ø¶ÔÓÚLinuxÕâÑùͨÓòÙ×÷ϵͳÕâÊDz»¿ÉÄܵġ£ Ïà¶Ô¶øÑÔ£¬¶Ô³Æ¶àÏ̴߳¦ÀíÊǽÏÈÝÒ×ʵÏֵġ£

    ÎÒÕâÀïËù˵µÄÏà¶ÔÈÝÒ×£¬ÀÏʵ˵£¬»¹ÊDz»ÈÝÒס£ÔÚÒ»¸ö¶Ô³Æ¶àÏ̴߳¦ÀíµÄ»·¾³ÖУ¬ ¶à¸öCPU¹²ÏíÄڴ棬µ¼ÖµĽá¹ûÊÇÆäÖÐÒ»¸öCPUÔËÐеĴúÂë»á¶Ô±ðµÄCPUÒ²²úÉúÓ°Ïì¡£ Äã²»ÄÜÔÙÈ·¶¨Äã´úÂëÖеÚÒ»ÐÐÖÐÉèÖõıäÁ¿ÔÚ½ÓÏÂÀ´µÄÄÇÐдúÂëÖл¹ÊÇÄǸöÉèÖÃÖµ£» ÆäËüµÄCPU¿ÉÄÜ»á³ÃÄã²»×¢ÒâÒѾ­°ÑËüÐÞ¸ÄÁË¡£ÏÔÈ»£¬Èç¹ûÊÇÕâÑùµÄ»°£¬ÊÇÎÞ·¨½øÐÐÈκαà³ÌµÄ¡£

    ¶ÔÓÚ½ø³Ì²ãÃæÉϵıà³ÌÕâͨ³£²»ÊǸöÎÊÌ⣬ÒòΪһ¸ö½ø³Ìͨ³£Í¬Ò»Ê±¼äÖ»ÔÚÒ»¸öCPUÉÏÔËÐÐ [1]¡£ µ«ÊÇ£¬¶ÔÓÚÄںˣ¬¾Í¿ÉÒÔ±»ÔÚ²»Í¬µÄCPUÉϵÄͬʱÔËÐеIJ»Í¬µÄ½ø³ÌʹÓá£

    ÔÚÄں˰汾2.0.xÖУ¬Õ⻹²»Ëã×÷ʲôÎÊÌ⣬ÒòΪÕû¸öÄÚºËÊÇÒ»¸öspinlock [2]£¬Õâ¾ÍÒâζ×ÅÒ»µ©Ä³¸öCPU½øÈëÄÚºË̬£¬±ðµÄCPU½«²»ÔÊÐí½øÈëÄÚºË̬¡£ÕâʹLinuxµÄSMPʵÏֺܰ²È« [3]£¬µ«È±·¦Ð§ÂÊ¡£

    ÔÚÄں˰汾2.2.xÒԺ󣬶àCPUÒѾ­ÔÊÐíͬʱ½øÈëÄÚºË̬¡£ÄÚºËÄ£¿éµÄ×÷ÕßÓ¦¸ÃÒâʶµ½ÕâÒ»µã¡£

    Notes
    [1] ´æÔÚÀýÍ⣬¾ÍÊÇÏ̻߳¯µÄ½ø³Ì£¬ÕâÑùµÄ½ø³Ì¿ÉÒÔÔÚ¶à¸öCPUÉÏͬʱÔËÐС£

    [2] ±§Ç¸£¬ÎÒûÓÐÕÒµ½ºÏÊʵĴÊÓïÀ´±í´ïÕâ¸öµ¥´Ê¡£ÕâÊÇÄÚºËÖеÄÒ»ÖÖ»úÖÆ£¬¿ÉÒÔ¶ÔÄÚºËÖеĹؼüÊý¾Ý½á¹¹½øÐÐËø¶¨±£»¤£¬ ·ÀÖ¹Æä±»ÆÆ»µ¡£

    [3] Òâζ×ÅÕâÑùµÄSMP»úÖÆʹÓÃÆðÀ´ºÜ°²È«¡£

  7. febspeolal ÓÚ 2006-11-09 01:12:31·¢±í:

    Chapter 12. Interrupt Handlers
    Interrupt Handlers
    Interrupt Handlers
    ³ýÁ˸սáÊøµÄÄÇÕ£¬ÎÒÃÇÄ¿Ç°ÔÚÄÚºËÖÐËù×öµÄÿ¼þʶ¼Ö»²»¹ýÊǶÔij¸öÇëÇóµÄ½ø³ÌµÄÏìÓ¦£¬ ҪôÊǶÔij¸öÌØÊâµÄÎļþµÄ´¦Àí£¬ÒªÃ´ÊÇ·¢ËÍÒ»¸öioctl()£¬ÒªÃ´Êǵ÷ÓÃÒ»¸öϵͳµ÷Óᣠµ«ÊÇÄں˵Ť×÷²»½ö½öÊÇÏìӦij¸ö½ø³ÌµÄÇëÇó¡£»¹ÓÐÁíÍâÒ»Ïî·Ç³£ÖØÒªµÄ¹¤×÷¾ÍÊǸºÔð¶ÔÓ²¼þµÄ¹ÜÀí¡£

    ÔÚCPUºÍÓ²¼þÖ®¼äµÄ»î¶¯´óÖ¿ɷÖΪÁ½ÖÖ¡£µÚÒ»ÖÖÊÇCPU·¢ËÍÖ¸Áî¸øÓ²¼þ£¬µÚ¶þÖÖ¾ÍÊÇÓ²¼þÒª·µ»ØijЩÐÅÏ¢¸øCPU¡£ ºóÃæµÄÄÇÖÖÓÖ½Ð×öÖжϣ¬ÒòΪҪ֪µÀºÎʱͬӲ¼þ¶Ô»°²ÅÊÊÒ˶ø½ÏÄÑʵÏÖ¡£Ó²¼þÉ豸ͨ³£Ö»ÓкÜÉٵĻº´æ£¬ Èç¹ûÄã²»¼°Ê±µÄ¶ÁÈ¡ÀïÃæµÄÐÅÏ¢£¬ÕâЩÐÅÏ¢¾Í»á¶ªÊ§¡£

    ÔÚLinuxÖУ¬Ó²¼þÖжϱ»½Ð×÷IRQ£¨Interrupt Requests£¬ÖжÏÇëÇó£©[1]¡£ÓÐÁ½ÖÖÓ²¼þÖжϣ¬¶ÌÖжϺͳ¤Öжϡ£¶ÌÖжÏÕ¼ÓõÄʱ¼ä·Ç³£¶Ì£¬ÔÚÕâ¶Îʱ¼äÄÚ£¬ Õû¸öϵͳ±»×èÈû£¬ÈκÎÆäËüÖж϶¼²»»á´¦Àí¡£³¤ÖжÏÕ¼ÓõÄʱ¼äÏà¶Ô½Ï³¤£¬ÔÚ´ËÆڼ䣬¿ÉÄÜ»áÓбðµÄÖжϷ¢ÉúÇëÇó´¦Àí £¨²»ÊÇÏàͬÉ豸·¢³öµÄÖжϣ©¡£¿ÉÄܵĻ°£¬¾¡Á¿½«ÖжÏÉùÃ÷Ϊ³¤Öжϡ£

    µ±CPU½ÓÊÕµ½Ò»¸öÖжÏʱ£¬ËüÍ£Ö¹ÕýÔÚ´¦ÀíµÄÒ»ÇÐÊÂÎñ£¨³ý·ÇËüÔÚ´¦ÀíÁíÒ»¸ö¸üÖØÒªµÄÖжϣ¬ ÔÚÕâÖÖÇé¿öÏÂËüÖ»»á´¦ÀíÍêÕâ¸öÖØÒªµÄÖжϲŻá»ØÀ´´¦ÀíвúÉúµÄÖжϣ©£¬ ½«ÔËÐÐÖеÄÄÇЩ²ÎÊýѹÈëÕ»ÖÐÈ»ºóµ÷ÓÃÖжϴ¦Àí³ÌÐò¡£ÕâͬʱÒâζ×ÅÖжϴ¦Àí³ÌÐò±¾ÉíÒ²ÓÐһЩÏÞÖÆ£¬ ÒòΪ´ËʱϵͳµÄ״̬²¢²»È·¶¨¡£½â¾öµÄ°ì·¨ÊÇÈÃÖжϴ¦Àí³ÌÐò¾¡¿ìµÄÍê³ÉËüµÄÊÂÎñ£¬Í¨³£ÊÇ´ÓÓ²¼þ¶ÁÈ¡ÐÅÏ¢ºÍÏòÓ²¼þ·¢ËÍÖ¸Á È»ºó°²ÅÅÏÂÒ»´Î½ÓÊÕÐÅÏ¢µÄÏà¹Ø´¦Àí£¨Õâ±»³ÆΪ"bottom half" [2] )£¬È»ºó·µ»Ø¡£ÄÚºËÈ·±£±»°²ÅŵÄÊÂÎñ±»¾¡¿ìµÄÖ´ÐС£µ±±»Ö´ÐÐʱ£¬ÔÚÄÚºËÄ£¿éÖÐÔÊÐíµÄ²Ù×÷¾ÍÊDZ»ÔÊÐíµÄ¡£

    ʵÏֵķ½·¨Êǵ÷ÓÃrequest_irq()º¯Êý£¬µ±½ÓÊܵ½ÏàÓ¦µÄIRQʱ £¨¹²ÓÐ15ÖÖÖжϣ¬ÔÚIntel¼Ü¹¹Æ½Ì¨ÉÏÔÙ¼ÓÉÏ1ÖÖÓÃÓÚ´®Á¬ÖжϿØÖÆÆ÷µÄÖжϣ©È¥µ÷ÓÃÄãµÄÖÐ¶Ï ´¦Àí³ÌÐò¡£¸Ãº¯Êý½ÓÊÕIRQºÅ£¬Òªµ÷ÓõĴ¦ÀíIRQº¯ÊýµÄÃû³Æ£¬ÖжÏÇëÇóµÄÀà±ð±ê־룬Îļþ /proc/interruptsÖÐÉùÃ÷µÄÉ豸µÄÃû×Ö£¬ºÍ´«µÝ¸øÖжϴ¦Àí³ÌÐòµÄ²ÎÊý¡£ÖжÏÇëÇóµÄÀà±ð±ê־λ¿ÉÒÔΪ SA_SHIRQÀ´¸æËßϵͳÄãÏ£ÍûÓëÆäËüÖжϴ¦Àí³ÌÐò¹²Ïí¸ÃÖжϺŠ£¨Õâͨ³£ÊÇÓÉÓÚһЩÉ豸¹²ÓÃÏàͬµÄIRQºÅ£©£¬Ò²¿ÉÒÔΪSA_INTERRUPT À´¸æËßϵͳÕâÊÇÒ»¸ö¿ìËÙÖжϣ¬ÕâÖÖÇé¿öϸú¯ÊýÖ»ÓÐÔÚ¸ÃIRQ¿ÕÏÐʱ²Å»á³É¹¦·µ»Ø£¬»òÕßͬʱÄãÓÖ¾ö¶¨¹²Ïí¸ÃIQR¡£

    È»ºó£¬ÔÚÖжϴ¦Àí³ÌÐòÄÚ²¿£¬ÎÒÃÇÓëÓ²¼þ¶Ô»°£¬½Ó×ÅʹÓôøtq_immediate()ºÍ mark_bh(BH_IMMEDIATE)µÄ queue_task_irq()È¥¶Ôbottom half¶ÓÁнøÐе÷¶È¡£ÎÒÃDz»ÄÜʹÓÃ2.0°æ±¾ÖÖ±ê×¼µÄ queue_task µÄÔ­ÒòÊÇÖжϿÉÄܾͷ¢ÉúÔÚ±ðÈ赀 queue_task[3] ÖС£ÎÒÃÇÐèÒªmark_bhÊÇÒòΪÔçÆÚ°æ±¾µÄLinuxÖ»ÓÐÒ»¸ö¿ÉÒÔ´æ´¢32¸öbottom halfµÄÊý×飬 ²¢ÇÒÏÖÔÚËüÃÇÖеÄÒ»¸ö(BH_IMMEDIATE)ÒѾ­±»ÓÃÀ´Á¬½ÓûÓзÖÅäµ½¶ÓÁÐÖеÄÈë¿ÚµÄÓ²¼þ Çý¶¯µÄbottom half¡£

    Intel¼Ü¹¹ÖеļüÅÌ
    Ê£ÓàµÄÕⲿ·ÖÊÇÖ»ÊÊÓÃIntel¼Ü¹¹µÄ¡£Èç¹ûÄ㲻ʹÓÃIntel¼Ü¹¹µÄƽ̨£¬ËüÃǽ«²»»á¹¤×÷£¬²»ÒªÈ¥³¢ÊÔ±àÒëÒÔϵĴúÂë¡£

    ÔÚдÕâÕµÄÊÂÀý´úÂëʱ£¬ÎÒÓöµ½ÁËһЩÀ§ÄÑ¡£Ò»·½Ã棬ÎÒÐèÒªÒ»¸ö¿ÉÒԵõ½Êµ¼ÊÓÐÒâÒå½á¹ûµÄ£¬ ÄÜÔÚ¸÷ÖÖƽ̨ÉϹ¤×÷µÄÀý×Ó¡£ÁíÒ»·½Ã棬ÄÚºËÖÐÒѾ­°üÀ¨Á˸÷ÖÖÉ豸Çý¶¯£¬²¢ÇÒÕâЩÇý¶¯½«ÎÞ·¨ºÍÎÒµÄÀý×Ó¹²´æ¡£ ÎÒÕÒµ½µÄ½â¾ö°ì·¨ÊÇΪ¼üÅÌÖжÏдµã¶«Î÷£¬µ±È»Ê×ÏȽûÓÃÆÕͨµÄ¼üÅÌÖжϡ£ÒòΪ¸ÃÖжÏÔÚÄÚºËÖж¨ÒåΪһ¸ö¾²Ì¬Á¬½ÓµÄ·ûºÅ £¨¼ûdrivers/char/keyboard.c)£©£¬ÎÒÃÇûÓа취»Ö¸´¡£ËùÒÔÔÚ insmodÇ°£¬Èç¹ûÄ㰮ϧÄãµÄ»úÆ÷£¬Ð´ò¿ªÒ»¸öÖÕ¶ËÔËÐÐsleep 120 ; reboot¡£

    ¸Ã´úÂ뽫×Ô¼º°ó¶¨ÔÚIRQ 1£¬ Ò²¾ÍÊÇIntel¼Ü¹¹ÖмüÅ̵ÄIRQ¡£È»ºó£¬µ±½ÓÊÕµ½Ò»¸ö¼üÅÌÖжÏÇëÇóʱ£¬Ëü¶ÁÈ¡¼üÅ̵Ä״̬£¨ÄǾÍÊÇ inb(0x64)µÄÄ¿µÄ£©ºÍɨÃèÂ룬Ҳ¾ÍÊǼüÅÌ·µ»ØµÄ¼üÖµ¡£È»ºó£¬Ò»µ©ÄÚºËÈÏΪÕâÊÇ·ûºÏÌõ¼þµÄ£¬ËüÔËÐÐ got_charÈ¥¸ø³ö²Ù×÷µÄ¼ü£¨É¨ÃèÂëµÄÍ·7¸ö룩ºÍÊÇ°´Ï¼ü£¨É¨ÃèÂëµÄµÚ8λΪ0£© »¹Êǵ¯Æð¼ü£¨É¨ÃèÂëµÄµÚ8λΪ1£©¡£

    Example 12-1. intrpt.c

    /*
    * intrpt.c - An interrupt handler.
    *
    * Copyright (C) 2001 by Peter Jay Salzman
    */

    /*
    * The necessary header files
    */

    /*
    * Standard in kernel modules
    */
    #include /* We're doing kernel work */
    #include /* Specifically, a module */
    #include
    #include
    #include /* We want an interrupt */
    #include

    #define MY_WORK_QUEUE_NAME "WQsched.c"

    static struct workqueue_struct *my_workqueue;

    /*
    * This will get called by the kernel as soon as it's safe
    * to do everything normally allowed by kernel modules.
    */
    static void got_char(void *scancode)
    {
    printk("Scan Code %x %s.\n",
    (int)*((char *)scancode) & 0x7F,
    *((char *)scancode) & 0x80 ? "Released" : " Pressed" );
    }

    /*
    * This function services keyboard interrupts. It reads the relevant
    * information from the keyboard and then puts the non time critical
    * part into the work queue. This will be run when the kernel considers it safe.
    */
    irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
    {
    /*
    * This variables are static because they need to be
    * accessible (through pointers) to the bottom half routine.
    */
    static int initialised = 0;
    static unsigned char scancode;
    static struct work_struct task;
    unsigned char status;

    /*
    * Read keyboard status
    */
    status = inb(0x64);
    scancode = inb(0x60);

    if (initialised == 0) {
    INIT_WORK(&task, got_char, &scancode);
    initialised = 1;
    } else {
    PREPARE_WORK(&task, got_char, &scancode);
    }

    queue_work(my_workqueue, &task);

    return IRQ_HANDLED;
    }

    /*
    * Initialize the module - register the IRQ handler
    */
    int init_module()
    {
    my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME);

    /*
    * Since the keyboard handler won't co-exist with another handler,
    * such as us, we have to disable it (free its IRQ) before we do
    * anything. Since we don't know where it is, there's no way to
    * reinstate it later - so the computer will have to be rebooted
    * when we're done.
    */
    free_irq(1, NULL);

    /*
    * Request IRQ 1, the keyboard IRQ, to go to our irq_handler.
    * SA_SHIRQ means we're willing to have othe handlers on this IRQ.
    * SA_INTERRUPT can be used to make the handler into a fast interrupt.
    */
    return request_irq(1, /* The number of the keyboard IRQ on PCs */
    irq_handler, /* our handler */
    SA_SHIRQ, "test_keyboard_irq_handler",
    (void *)(irq_handler));
    }

    /*
    * Cleanup
    */
    void cleanup_module()
    {
    /*
    * This is only here for completeness. It's totally irrelevant, since
    * we don't have a way to restore the normal keyboard interrupt so the
    * computer is completely useless and has to be rebooted.
    */
    free_irq(1, NULL);
    }

    /*
    * some work_queue related functions are just available to GPL licensed Modules
    */
    MODULE_LICENSE("GPL" );
    Notes
    [1] ÕâÊÇLinuxÆðÔ´µÄIntel¼Ü¹¹Öеıê×¼µÄÆðÃû·½·¨¡£


    [2] ÕâÀïÊÇÒëÕ߸ø³öµÄ¹ØÓÚ¡°bottom half¡±µÄÒ»µã½âÊÍ£¬À´Ô´ÊÇgoogleÉÏËÑË÷µ½µÄÓ¢ÎÄ×ÊÁÏ£º

    ¡°µ×²¿¡±£¬¡°bottom half¡±³£ÔÚÉæ¼°ÖжϵÄÉ豸Çý¶¯ÖÐÌáµ½¡£


    µ±Äں˽ÓÊÕµ½Ò»¸öÖжÏÇëÇ󣬶ÔÓ¦µÄÉ豸Çý¶¯±»µ÷Óá£ÒòΪÔÚÕâ¶Îʱ¼äÄÚÎÞ·¨´¦Àí±ðµÄÈκÎÊÂÎñ£¬ ÈÃÖжϴ¦Àí¾¡¿ìµÄÍê³É²¢ÖØÐÂÈÃÄں˷µ»ØÕý³£µÄ¹¤×÷״̬ÊǷdz£ÖØÒªµÄ¡£¾ÍÊÇÒòΪÕâ¸öÉè¼Æ˼Ï룬 Çý¶¯µÄ¡°¶¥²¿¡±ºÍ¡°µ×²¿¡±µÄ¸ÅÄî±»Ìá³ö£º¡°¶¥²¿¡±ÊDZ»Äں˵÷ÓÃʱ×îÏȱ»Ö´ÐеIJ¿·Ö£¬ ¿ìËÙµÄÍê³ÉһЩ¾¡Á¿ÉÙµÄÈ´ÊDZØÐèµÄ¹¤×÷£¨Ïñ¶ÔÓ²¼þ»òÆäËü×ÊÔ´µÄ¶ÀÏí·ÃÎÊÕâÖÖ±ØÐëÁ¢¿ÌÖ´ÐеIJÙ×÷£©£¬ È»ºó×öһЩÉèÖÃÈᰵײ¿¡±È¥Íê³ÉÄÇЩҪÇóʱ¼äÏà¶Ô±È½Ï¿íÔ£µÄ£¬Ê£ÏµĹ¤×÷¡£

    ¡°µ×²¿¡±Ê²Ã´Ê±ºòÈçºÎÔË×÷ÊÇÄں˵ÄÉè¼ÆÎÊÌâ¡£ÄãÒ²Ðí»áÌýµ½¡°µ×²¿¡±µÄÉè¼ÆÒѾ­ÔÚ×î½üµÄÄÚºËÖб»·Ï³ýÁË¡£ ÕâÖÖ˵·¨²»ÊǺÜÈ·ÇУ¬ÔÚÐÂÄÚºËÖÐÆäʵÄã¿ÉÒÔȥѡÔñÔõÑùÈ¥Ö´ÐУºÏñÈíÖжϻòÈÎÎñ£¬¾ÍÏñËüÃÇÒÔÇ°ÄÇÑù£¬ »¹ÊǼÓÈëÈÎÎñ¶ÓÁУ¬¸üÏñÆô¶¯Ò»¸öÓû§½ø³Ì¡£

    [3] queue_task_irq±»Ò»¸öÈ«¾ÖµÄËø£¨ÓÐËø¶¨×÷ÓõıäÁ¿£© ±£»¤×Å£¬ÔÚ°æ±¾2.2ÖУ¬²¢Ã»ÓÐqueue_task_irq¶øÇÒqueue_task Ò²ÊDZ»Ò»¸öËø±£»¤µÄ¡£

  8. febspeolal ÓÚ 2006-11-09 01:12:10·¢±í:

    Chapter 11. Scheduling Tasks
    ÈÎÎñµ÷¶È
    ¾­³£ÎÒÃÇÒª¶¨Æڵijé¿Õ´¦ÀíһЩ¡°¼ÒÎñ»î¡±¡£Èç¹ûÕâÑùµÄÈÎÎñͨ¹ýÒ»¸öÓû§½ø³ÌÍê³ÉµÄ£¬ÄÇôÎÒÃÇ¿ÉÒÔ½«Ëü·Åµ½Ò»¸ö crontabÎļþÖС£Èç¹ûÊÇͨ¹ýÒ»¸öÄÚºËÄ£¿éÀ´Íê³É£¬ÄÇôÎÒÃÇÓÐÁ½ÖÖÑ¡Ôñ¡£ µÚÒ»ÖÖÑ¡ÔñÊÇʹÓÃcrontabÎļþ£¬Æô¶¯Ò»¸ö½ø³Ì£¬Í¨¹ýÒ»¸öϵͳµ÷Óû½ÐÑÄÚºËÄ£¿é£¬ÀýÈç´ò¿ªÒ»¸öÎļþ¡£ ÕâºÜûЧÂÊ¡£ÎÒÃÇͨ¹ýcrontabÉú³ÉÁËÒ»¸öнø³Ì£¬¶ÁÈ¡ÁËÒ»¶ÎеĿÉÖ´ÐдúÂë½øÈëÄڴ棬 Ö»ÊÇΪÁË»½ÐÑÒ»¸öÒѾ­ÔÚÄÚ´æÖеÄÄÚºËÄ£¿é¡£

    µÚ¶þÖÖÑ¡ÔñÊÇÎÒÃǹ¹ÔìÒ»¸öº¯Êý£¬È»ºó¸Ãº¯ÊýÔÚÿ´Îʱ¼äÖжϷ¢Éúʱ±»µ÷Óá£ÊµÏÖ·½·¨ÊÇÎÒÃǹ¹ÔìÒ»¸öÈÎÎñ£¬Ê¹ÓýṹÌå tq_struct£¬¶ø¸Ã½á¹¹ÌåÓÖ±£´æ×ÅÖ¸Ïò¸Ãº¯ÊýµÄÖ¸Õ롣Ȼºó£¬ÎÒÃÇÓà queue_task°Ñ¸ÃÈÎÎñ·ÅÔÚ½Ð×ötq_timerÈÎÎñ¶ÓÁÐÖС£ ¸Ã¶ÓÁÐÊǽ«ÔÚϸöʱ¼äÖжϷ¢ÉúʱִÐеÄÈÎÎñ¡£ÒòΪÎÒÃÇÏëҪʹËü²»Í£µÄÖ´ÐУ¬ËùÒÔµ±¸Ãº¯ÊýÖ´ÐÐÍêºóÎÒÃÇ»¹Òª½«Ëü·Å»Ø tq_timerÈÎÎñ¶ÓÁÐÖеȴýÏÂÒ»´Îʱ¼äÖжϡ£

    µ«ÎÒÃÇËƺõÍüÁËÒ»µã¡£µ±Ò»¸öÄ£¿éÓÃrmmodжÔØʱ£¬Ëü»á¼ì²éʹÓüÆÊý¡£ Èç¹û¸Ã¼ÆÊýΪÁ㣬Ôòµ÷ÓÃmodule_cleanup¡£È»ºó£¬Ä£¿é¾ÍͬËüµÄËùÓк¯Êýµ÷ÓôÓÄÚ´æÖÐÏûʧÁË¡£ ´ËʱûÈËÈ¥¼ì²éÈÎÎñ¶ÓÁÐÖÐÊÇ·ñÕýºÃ»¹ÓÐÒ»¸öµÈ´ýÖ´ÐеÄÕâЩº¯ÊýµÄÖ¸Õë¡£ÔÚ¿ÉÄÜÊÇÒ»¶ÎÂþ³¤µÄʱ¼äºó £¨µ±È»ÊÇÏà¶Ô¼ÆËã»ú¶øÑÔ£¬¶ÔÓÚÎÒÃÇÕâµãʱ¼äʲô¶¼²»ÊÇ£¬Ò²¾Í²î²»¶à°Ù·ÖÖ®Ò»Ãë°É£©£¬ Äں˽ÓÊÕµ½Ò»¸öʱ¼äÖжϣ¬È»ºó×¼±¸µ÷ÓÃÄǸöÔÚÈÎÎñ¶ÓÁÐÖеĺ¯Êý¡£²»ÐÒµÄÊÇ£¬¸Ãº¯ÊýÒѾ­²»´æÔÚÁË¡£ ´ó¶àÊýÇé¿öÏ£¬ÓÉÓÚ·ÃÎʵÄÄÚ´æÒ³Êǿհ׵ģ¬ÄãÖ»»áÊÕµ½Ò»¸ö²»Óä¿ìµÄÏûÏ¢¡£µ«ÊÇÈç¹ûÆäËüµÄһЩ´úÂëÇ¡ºÃ¾ÍÔÚÄÇÀ ½á¹û¿ÉÄܽ«»á·Ç³£Ôã¸â¡£Í¬Ñù²»ÐÒµÄÊÇ£¬ÎÒÃÇҲûÓÐÒ»ÖÖÇáÒ×µÄÏòÈÎÎñ¶ÓÁÐ×¢ÏúÈÎÎñµÄ»úÖÆ¡£

    ¼ÈÈ»cleanup_module²»ÄÜ·µ»ØÒ»¸ö´íÎó´úÂ루ËüÊÇÒ»¸övoidº¯Êý£©£¬ ½â¾öÖ®µÀÊÇÈÃËü²»Òª·µ»Ø¡£Ïà·´£¬µ÷ÓÃsleep_on»òmodule_sleep_on [1]Èà rmmodµÄ½ø³ÌÐÝÃß¡£ÔÚ´Ë֮ǰ£¬Ëü֪ͨ±»Ê±¼äÖжϵ÷¶È³öÈÎÎñ¶ÓÁеÄÄǸöº¯Êý²»ÒªÔÚ·µ»Ø¶ÓÁС£ ÕâÑù£¬ÔÚÏÂÒ»¸öʱ¼äÖжϷ¢Éúʱ£¬rmmod¾Í»á±»»½ÐÑ£¬´ËʱÎÒÃǵĺ¯ÊýÒѾ­²»ÔÚ¶ÓÁÐÖУ¬ ¿ÉÒԺܰ²È«µÄжÔØÎÒÃǵÄÄ£¿éÁË¡£

    Example 11-1. sched.c

    /*
    * sched.c - scheduale a function to be called on every timer interrupt.
    *
    * Copyright (C) 2001 by Peter Jay Salzman
    */

    /*
    * The necessary header files
    */

    /*
    * Standard in kernel modules
    */
    #include /* We're doing kernel work */
    #include /* Specifically, a module */
    #include /* Necessary because we use the proc fs */
    #include /* We scheduale tasks here */
    #include /* We need to put ourselves to sleep
    and wake up later */
    #include /* For __init and __exit */
    #include /* For irqreturn_t */

    struct proc_dir_entry *Our_Proc_File;
    #define PROC_ENTRY_FILENAME "sched"
    #define MY_WORK_QUEUE_NAME "WQsched.c"

    /*
    * The number of times the timer interrupt has been called so far
    */
    static int TimerIntrpt = 0;

    static void intrpt_routine(void *);

    static int die = 0; /* set this to 1 for shutdown */

    /*
    * The work queue structure for this task, from workqueue.h
    */
    static struct workqueue_struct *my_workqueue;

    static struct work_struct Task;
    static DECLARE_WORK(Task, intrpt_routine, NULL);

    /*
    * This function will be called on every timer interrupt. Notice the void*
    * pointer - task functions can be used for more than one purpose, each time
    * getting a different parameter.
    */
    static void intrpt_routine(void *irrelevant)
    {
    /*
    * Increment the counter
    */
    TimerIntrpt++;

    /*
    * If cleanup wants us to die
    */
    if (die == 0)
    queue_delayed_work(my_workqueue, &Task, 100);
    }

    /*
    * Put data into the proc fs file.
    */
    ssize_t
    procfile_read(char *buffer,
    char **buffer_location,
    off_t offset, int buffer_length, int *eof, void *data)
    {
    int len; /* The number of bytes actually used */

    /*
    * It's static so it will still be in memory
    * when we leave this function
    */
    static char my_buffer[80];

    static int count = 1;

    /*
    * We give all of our information in one go, so if the anybody asks us
    * if we have more information the answer should always be no.
    */
    if (offset > 0)
    return 0;

    /*
    * Fill the buffer and get its length
    */
    len = sprintf(my_buffer, "Timer called %d times so far\n", TimerIntrpt);
    count++;

    /*
    * Tell the function which called us where the buffer is
    */
    *buffer_location = my_buffer;

    /*
    * Return the length
    */
    return len;
    }

    /*
    * Initialize the module - register the proc file
    */
    int __init init_module()
    {
    int rv = 0;
    /*
    * Put the task in the work_timer task queue, so it will be executed at
    * next timer interrupt
    */
    my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME);
    queue_delayed_work(my_workqueue, &Task, 100);

    Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
    Our_Proc_File->read_proc = procfile_read;
    Our_Proc_File->owner = THIS_MODULE;
    Our_Proc_File->mode = S_IFREG | S_IRUGO;
    Our_Proc_File->uid = 0;
    Our_Proc_File->gid = 0;
    Our_Proc_File->size = 80;

    if (Our_Proc_File == NULL) {
    rv = -ENOMEM;
    remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
    printk(KERN_INFO "Error: Could not initialize /proc/%s\n",
    PROC_ENTRY_FILENAME);
    }

    return rv;
    }

    /*
    * Cleanup
    */
    void __exit cleanup_module()
    {
    /*
    * Unregister our /proc file
    */
    remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
    printk(KERN_INFO "/proc/%s removed\n", PROC_ENTRY_FILENAME);

    die = 1; /* keep intrp_routine from queueing itself */
    cancel_delayed_work(&Task); /* no "new ones" */
    flush_workqueue(my_workqueue); /* wait till all "old ones" finished */
    destroy_workqueue(my_workqueue);

    /*
    * Sleep until intrpt_routine is called one last time. This is
    * necessary, because otherwise we'll deallocate the memory holding
    * intrpt_routine and Task while work_timer still references them.
    * Notice that here we don't allow signals to interrupt us.
    *
    * Since WaitQ is now not NULL, this automatically tells the interrupt
    * routine it's time to die.
    */

    }

    /*
    * some work_queue related functions
    * are just available to GPL licensed Modules
    */
    MODULE_LICENSE("GPL" );
    Notes
    [1] ËüÃÇʵ¼ÊÉÏÊÇÒ»»ØÊ¡£

  9. febspeolal ÓÚ 2006-11-09 01:11:48·¢±í:

    Chapter 10. Replacing Printks
    Table of Contents
    Ìæ»»printk
    ÈÃÄãµÄ¼üÅÌָʾµÆÉÁÆðÀ´
    Ìæ»»printk
    ÔÚthe Section called ʹÓà X´øÀ´µÄÎÊÌâ in Chapter 1ÖУ¬ ÎÒ˵¹ý×îºÃ²»ÒªÔÚXÖнøÐÐÄÚºËÄ£¿é±à³Ì¡£ÔÚÕæÕýµÄÄÚºËÄ£¿é¿ª·¢ÖеÄÈ·ÊÇÕâÑù¡£ µ«ÔÚʵ¼ÊÓ¦ÓÃÖУ¬ÄãÏëÔÚÈκμÓÔØÄ£¿éµÄtty[1]ÖÕ¶ËÖÐÏÔʾÐÅÏ¢¡£

    ʵÏֵķ½·¨ÊÇʹÓÃcurrentÖ¸Õ룬һ¸öÖ¸Ïòµ±Ç°ÔËÐнø³ÌµÄÖ¸Õ룬À´»ñÈ¡µ±Ç°ÈÎÎñµÄ ttyÖն˵ĽṹÌ塣Ȼºó£¬ÎÒÃÇÕÒµ½ÔÚ¸Ãtty½á¹¹ÌåÖÐ ÓÃÀ´ÏòttyдÈë×Ö·ûÐÅÏ¢µÄº¯ÊýµÄÖ¸Õ롣ͨ¹ýÖ¸ÕëÎÒÃÇʹÓøú¯ÊýÀ´ÏòÖÕ¶ËдÈëÐÅÏ¢¡£

    Example 10-1. print_string.c

    /*
    * print_string.c - Send output to the tty we're running on, regardless if it's
    * through X11, telnet, etc. We do this by printing the string to the tty
    * associated with the current task.
    */
    #include
    #include
    #include
    #include /* For current */
    #include /* For the tty declarations */
    #include /* For LINUX_VERSION_CODE */

    MODULE_LICENSE("GPL" );
    MODULE_AUTHOR(" Peter Jay Salzman" );

    static void print_string(char *str)
    {
    struct tty_struct *my_tty;

    /*
    * tty struct went into signal struct in 2.6.6
    */
    #if ( LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,5) )
    /*
    * The tty for the current task
    */
    my_tty = current->tty;
    #else
    /*
    * The tty for the current task, for 2.6.6+ kernels
    */
    my_tty = current->signal->tty;
    #endif

    /*
    * If my_tty is NULL, the current task has no tty you can print to
    * (ie, if it's a daemon). If so, there's nothing we can do.
    */
    if (my_tty != NULL) {

    /*
    * my_tty->driver is a struct which holds the tty's functions,
    * one of which (write) is used to write strings to the tty.
    * It can be used to take a string either from the user's or
    * kernel's memory segment.
    *
    * The function's 1st parameter is the tty to write to,
    * because the same function would normally be used for all
    * tty's of a certain type. The 2nd parameter controls whether
    * the function receives a string from kernel memory (false, 0)
    * or from user memory (true, non zero). The 3rd parameter is
    * a pointer to a string. The 4th parameter is the length of
    * the string.
    */
    ((my_tty->driver)->write) (my_tty, /* The tty itself */
    0, /* Don't take the string
    from user space */
    str, /* String */
    strlen(str)); /* Length */

    /*
    * ttys were originally hardware devices, which (usually)
    * strictly followed the ASCII standard. In ASCII, to move to
    * a new line you need two characters, a carriage return and a
    * line feed. On Unix, the ASCII line feed is used for both
    * purposes - so we can't just use \n, because it wouldn't have
    * a carriage return and the next line will start at the
    * column right after the line feed.
    *
    * This is why text files are different between Unix and
    * MS Windows. In CP/M and derivatives, like MS-DOS and
    * MS Windows, the ASCII standard was strictly adhered to,
    * and therefore a newline requirs both a LF and a CR.
    */
    ((my_tty->driver)->write) (my_tty, 0, "\015\012", 2);
    }
    }

    static int __init print_string_init(void)
    {
    print_string("The module has been inserted. Hello world!" );
    return 0;
    }

    static void __exit print_string_exit(void)
    {
    print_string("The module has been removed. Farewell world!" );
    }

    module_init(print_string_init);
    module_exit(print_string_exit);
    Notes
    [1] Teletype, Ô­ÏÈÊÇÒ»ÖÖÓÃÀ´ºÍUnixϵͳ½»»¥µÄ¼üÅ̺ʹòÓ¡»ú½áºÏÆðÀ´µÄ×°Öá£ÏÖÔÚ£¬ËüÖ»ÊÇÒ»¸öÓÃÀ´Í¬Unix»òÀàËƵÄϵͳ½»Á÷ÎÄ×ÖÁ÷ µÄ³éÏóµÄÉ豸£¬¶ø²»¹ÜËü¾ßÌåÊÇÏÔʾÆ÷£¬XÖеÄxterm£¬»¹ÊÇÒ»¸öͨ¹ýtelnetµÄÍøÂçÁ¬½Ó¡£
    ÈÃÄãµÄ¼üÅÌָʾµÆÉÁÆðÀ´
    ÄãÒ²ÐíÏëÈÃÄãµÄÄ£¿é¸üÖ±½ÓµÄͬÍâ½ç½»Á÷£¬ÄãµÄ¼üÅÌָʾµÆ¾ÍÊÇÒ»¸ö²»´íµÄÑ¡Ôñ¡£Ëü¿ÉÒÔ¼°Ê±ÏÔʾģ¿éµÄ¹¤×÷״̬£¬ ÎüÒýÄãµÄ×¢Ò⣬²¢ÇÒËüÃDz»ÐíÒªÈκÎÉèÖã¬Ê¹ÓÃÆðÀ´Ò²²»ÏñÏòÖն˻ò´ÅÅÌдÈëÐÅÏ¢ÄÇôΣÏÕ¡£

    ÏÂÃæµÄÕâ¸öÄ£¿é´úÂëÑÝʾÁËÒ»¸öÏ൱СµÄÄ£¿é£ºµ±±»¼ÓÔØÈëÄÚºËʱ£¬¼üÅÌָʾµÆ¾Í²»Í£µÄÉÁ˸£¬Ö±µ½Ëü±»Ð¶ÔØ¡£

    Example 10-2. kbleds.c

    /*
    * kbleds.c - Blink keyboard leds until the module is unloaded.
    */

    #include
    #include
    #include
    #include /* For fg_console, MAX_NR_CONSOLES */
    #include /* For KDSETLED */
    #include /* For vc_cons */

    MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs.");
    MODULE_AUTHOR("Daniele Paolo Scarpazza");
    MODULE_LICENSE("GPL");

    struct timer_list my_timer;
    struct tty_driver *my_driver;
    char kbledstatus = 0;

    #define BLINK_DELAY HZ/5
    #define ALL_LEDS_ON 0x07
    #define RESTORE_LEDS 0xFF

    /*
    * Function my_timer_func blinks the keyboard LEDs periodically by invoking
    * command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual
    * terminal ioctl operations, please see file:
    * /usr/src/linux/drivers/char/vt_ioctl.c, function vt_ioctl().
    *
    * The argument to KDSETLED is alternatively set to 7 (thus causing the led
    * mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF
    * (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus
    * the LEDs reflect the actual keyboard status). To learn more on this,
    * please see file:
    * /usr/src/linux/drivers/char/keyboard.c, function setledstate().
    *
    */

    static void my_timer_func(unsigned long ptr)
    {
    int *pstatus = (int *)ptr;

    if (*pstatus == ALL_LEDS_ON)
    *pstatus = RESTORE_LEDS;
    else
    *pstatus = ALL_LEDS_ON;

    (my_driver->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDSETLED,
    *pstatus);

    my_timer.expires = jiffies + BLINK_DELAY;
    add_timer(&my_timer);
    }

    static int __init kbleds_init(void)
    {
    int i;

    printk(KERN_INFO "kbleds: loading\n");
    printk(KERN_INFO "kbleds: fgconsole is %x\n", fg_console);
    for (i = 0; i < MAX_NR_CONSOLES; i++) {
    if (!vc_cons[i].d)
    break;
    printk(KERN_INFO "poet_atkm: console[%i/%i] #%i, tty %lx\n", i,
    MAX_NR_CONSOLES, vc_cons[i].d->vc_num,
    (unsigned long)vc_cons[i].d->vc_tty);
    }
    printk(KERN_INFO "kbleds: finished scanning consoles\n");

    my_driver = vc_cons[fg_console].d->vc_tty->driver;
    printk(KERN_INFO "kbleds: tty driver magic %x\n", my_driver->magic);

    /*
    * Set up the LED blink timer the first time
    */
    init_timer(&my_timer);
    my_timer.function = my_timer_func;
    my_timer.data = (unsigned long)&kbledstatus;
    my_timer.expires = jiffies + BLINK_DELAY;
    add_timer(&my_timer);

    return 0;
    }

    static void __exit kbleds_cleanup(void)
    {
    printk(KERN_INFO "kbleds: unloading...\n");
    del_timer(&my_timer);
    (my_driver->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDSETLED,
    RESTORE_LEDS);
    }

    module_init(kbleds_init);
    module_exit(kbleds_cleanup);
    Èç¹ûÉÏÃæµÄ·½·¨¶¼ÎÞ·¨Âú×ãÄãµ÷ÊÔµÄÐèÒª£¬Äã¾Í¿ÉÄÜÐèÒªÆäËüµÄ¼¼ÇÉÁË¡£»¹¼ÇµÃÄǸöÔÚ make menuconfig ʱµÄCONFIG_LL_DEBUG²ÎÊýÂð£¿Èç¹ûÄ㼤»î¸ÃÑ¡ÏÄã¾Í¿ÉÒÔ»ñµÃ¶Ô´®¿ÚµÄµ×²ã²Ù×Ý¡£Èç¹ûÕâÈÔÈ»²»¹»Ë¬£¬Ä㻹¿ÉÒÔ¶Ô kernel/printk.c»òÆäËüµÄ»ù±¾µÄϵͳµ×²ãµ÷Óôò²¹¶¡À´Ê¹ÓÃprintascii£¬´Ó¶ø¿ÉÒÔͨ¹ý´®¿Ú¸ú×Ù Äں˵Äÿ²½¶¯×÷¡£Èç¹ûÄãµÄ¼Ü¹¹²»Ö§³ÖÉÏÃæµÄÀý×ÓÈ´ÓÐÒ»¸ö±ê×¼µÄ´®¿Ú£¬Õâ¿ÉÄÜÓ¦¸ÃÊÇÄãÊ×ÏÈÓ¦¸Ã¿¼ÂǵÄÁË¡£Í¨¹ýÍøÂçÉ쵀 Öն˵÷ÊÔͬÑùÖµµÃ³¢ÊÔ¡£

    ¾¡¹ÜÓкܶà¹ØÓÚÈçºÎµ÷ÊԵļ¼ÇÉ£¬µ«ÎÒÒªÌáÐѵÄÊÇÈκε÷ÊÔ¶¼»á´úÂë´øÀ´Ó°Ïì¡£¼ÓÈëµ÷ÊÔ´úÂë×ãÒÔµ¼ÖÂԭʼ´úÂë²úÉúbugµÄ Ìõ¼þµÄÏûʧ£¬ËùÒÔ¾¡¿ÉÄÜÉٵļÓÈëµ÷ÊÔ´úÂë²¢ÇÒÈ·±£ËüÃDz»³öÏÖÔÚ³ÉÊìµÄ´úÂëÖС£

  10. febspeolal ÓÚ 2006-11-09 01:11:23·¢±í:

    Chapter 9. Blocking Processes
    ×èÈû½ø³Ì
    Enter Sandman
    µ±±ðÈËÈÃÄã×öÒ»¼þÄã²»ÄÜÂíÉÏÈ¥×öµÄÊÂʱ£¬Äã»áÈçºÎ·´Ó³£¿Èç¹ûÄãÊÇÈËÀàµÄ»°£¬¶øÇÒ¶Ô·½Ò²ÊÇÈËÀàµÄ»°£¬ ÄãÖ»»á˵£º¡°ÏÖÔÚ²»ÐУ¬ÎÒæ×ÅÔÚ¡£ÉÁ¿ª£¡¡±µ«ÊÇÈç¹ûÄãÊÇÒ»¸öÄÚºËÄ£¿é¶øÇÒÄã±»Ò»¸ö½ø³ÌÒÔͬÑùµÄÎÊÌâÀ§ÈÅ£¬ Äã»áÓÐÁíÍâÒ»¸öÑ¡Ôñ¡£Äã¿ÉÒÔÈøýø³ÌÐÝÃßÖ±µ½Äã¿ÉÒÔΪËü·þÎñʱ¡£±Ï¾¹£¬ÕâÑùµÄÇé¿öÔÚÄÚºËÖÐʱʱ¿Ì¿Ì¶¼ÔÚ·¢Éú £¨Õâ¾ÍÊÇϵͳÈöà½ø³ÌÔÚµ¥CPUÉÏͬʱÔËÐеķ½·¨£©¡£

    Õâ¸öÄÚºËÄ£¿é¾ÍÊÇÒ»¸öÕâÑùµÄÀý×Ó¡£Îļþ£¨/proc/sleep)£©Ö»¿ÉÒÔÔÚͬһʱ¿Ì±»Ò»¸ö½ø³Ì´ò¿ª¡£ Èç¹û¸ÃÎļþÒѾ­±»´ò¿ª£¬ÄÚºËÄ£¿é½«µ÷Óú¯Êý wait_event_interruptible[1]¡£¸Ãº¯ÊýÐÞ¸ÄtaskµÄ״̬£¨taskÊÇÒ»¸öÄÚºËÖеĽṹÌåÊý¾Ý½á¹¹£¬ ÆäÖб£´æ×ŶÔÓ¦½ø³ÌµÄÐÅÏ¢ºÍ¸Ã½ø³ÌÕýÔÚµ÷ÓõÄϵͳµ÷Óã¬Èç¹ûÓеĻ°£©Îª TASK_INTERRUPTIBLEÒâζןĽø³Ì½«²»»á¼ÌÐøÔËÐÐÖ±µ½±»»½ÐÑ£¬È»ºó±»Ìí¼Óµ½ÏµÍ³µÄ½ø³ÌµÈ´ý¶ÓÁÐ WaitQÖУ¬Ò»¸öµÈ´ý´ò¿ª¸ÃÎļþµÄ¶ÓÁÐÖС£È»ºó£¬¸Ãº¯Êýµ÷ÓÃϵͳµ÷¶ÈÆ÷È¥Çл»µ½ÁíÒ»¸ö²»Í¬µÄ µ«ÓÐCPUÔËËãÇëÇóµÄ½ø³Ì¡£

    µ±Ò»¸ö½ø³Ì´¦ÀíÍê¸ÃÎļþ²¢ÇҹرÕÁ˸ÃÎļþ£¬module_close¾Í±»µ÷ÓÃÖ´ÐÐÁË¡£ ¸Ãº¯Êý»½ÐÑËùÓÐÔڵȴý¶ÓÁÐÖеĽø³Ì£¨»¹Ã»ÓÐÖ»»½ÐÑÌض¨½ø³ÌµÄ»úÖÆ£©¡£È»ºó¸Ãº¯Êý·µ»Ø£¬ ÄǸö¸Õ¸Õ¹Ø±ÕÎļþµÄ½ø³ÌµÃÒÔ¼ÌÐøÔËÐС£¼°Ê±µÄ£¬½ø³Ìµ÷¶ÈÆ÷»áÅж¨¸Ã½ø³ÌÖ´ÐÐÒÑÖ´ÐÐÍê±Ï£¬ ½«CPUתÈøø±ðµÄ½ø³Ì¡£±»ÌṩCPUʹÓÃȨµÄÄǸö½ø³Ì¾ÍÇ¡ºÃ´ÓÏÈǰϵͳµ÷Óà module_interruptible_sleep_on[2]ºóµÄµØ·½¿ªÊ¼¼ÌÐøÖ´ÐС£ Ëü¿ÉÒÔÉèÖÃÒ»¸öÈ«¾Ö±äÁ¿È¥Í¨Öª±ðµÄ½ø³Ì¸ÃÎļþÒѱ»´ò¿ªÕ¼ÓÃÁË¡£µ±±ðµÄÇëÇó¸ÃÎļþµÄ½ø³Ì»ñµÃCPUʱ¼äƬʱ£¬ ËüÃǽ«¼ì²â¸Ã±äÁ¿È»ºó·µ»ØÐÝÃß¡£

    ¸üÓÐȤµÄÊÇ£¬module_close²¢²»Â¢¶Ï»½ÐѵȴýÖеÄÇëÇóÎļþµÄ½ø³ÌµÄȨÁ¦¡£Ò»¸öÐźţ¬ÏñCtrl+c (SIGINTÒ²Äܹ»»½ÐѱðµÄ½ø³Ì [3]¡£ ÔÚÕâÖÖÇé¿öÏ£¬ÎÒÃÇÏëÁ¢¼´·µ»Ø-EINTR ¡£ Õâ¶ÔÓû§ºÜÖØÒª£¬¾Ù¸öÀý×ÓÀ´Ëµ£¬Óû§¿ÉÒÔÔÚij¸ö½ø³Ì½ÓÊܵ½ÎļþÇ°ÖÕÖ¹¸Ã½ø³Ì¡£

    »¹ÓÐÒ»µãÖµµÃ×¢Òâ¡£ÓÐЩʱºò½ø³Ì²¢²»Ô¸ÒâÐÝÃߣ¬ËüÃÇҪôÁ¢¼´Ö´ÐÐËüÃÇÏë×öµÄ£¬ Ҫô±»¸æÖªÈÎÎñÎÞ·¨½øÐС£ÕâÑùµÄ½ø³ÌÔÚ´ò¿ªÎļþʱ»áʹÓñêÖ¾O_NONBLOCK¡£ ÔÚ±ðµÄ½ø³Ì±»×èÈûʱÄÚºËÓ¦¸Ã×ö³öµÄÏìÓ¦ÊÇ·µ»Ø´íÎó´úÂë-EAGAIN£¬ÏñÔÚ±¾ÀýÖжԸÃÎļþµÄÇëÇóµÄ½ø³Ì¡£³ÌÐò cat_noblock£¬ÔÚ±¾ÕµÄÔ´´úÂëĿ¼Ï¿ÉÒÔÕÒµ½£¬¾ÍÄܹ»Ê¹Óñê־λ O_NONBLOCK´ò¿ªÎļþ¡£

    Example 9-1. sleep.c

    /*
    * sleep.c - create a /proc file, and if several processes try to open it at
    * the same time, put all but one to sleep
    */

    #include /* We're doing kernel work */
    #include /* Specifically, a module */
    #include /* Necessary because we use proc fs */
    #include /* For putting processes to sleep and
    waking them up */
    #include /* for get_user and put_user */

    /*
    * The module's file functions
    */

    /*
    * Here we keep the last message received, to prove that we can process our
    * input
    */
    #define MESSAGE_LENGTH 80
    static char Message[MESSAGE_LENGTH];

    static struct proc_dir_entry *Our_Proc_File;
    #define PROC_ENTRY_FILENAME "sleep"

    /*
    * Since we use the file operations struct, we can't use the special proc
    * output provisions - we have to use a standard read function, which is this
    * function
    */
    static ssize_t module_output(struct file *file, /* see include/linux/fs.h */
    char *buf, /* The buffer to put data to
    (in the user segment) */
    size_t len, /* The length of the buffer */
    loff_t * offset)
    {
    static int finished = 0;
    int i;
    char message[MESSAGE_LENGTH + 30];

    /*
    * Return 0 to signify end of file - that we have nothing
    * more to say at this point.
    */
    if (finished) {
    finished = 0;
    return 0;
    }

    /*
    * If you don't understand this by now, you're hopeless as a kernel
    * programmer.
    */
    sprintf(message, "Last input:%s\n", Message);
    for (i = 0; i < len && message[i]; i++)
    put_user(message[i], buf + i);

    finished = 1;
    return i; /* Return the number of bytes "read" */
    }

    /*
    * This function receives input from the user when the user writes to the /proc
    * file.
    */
    static ssize_t module_input(struct file *file, /* The file itself */
    const char *buf, /* The buffer with input */
    size_t length, /* The buffer's length */
    loff_t * offset)
    { /* offset to file - ignore */
    int i;

    /*
    * Put the input into Message, where module_output will later be
    * able to use it
    */
    for (i = 0; i < MESSAGE_LENGTH - 1 && i < length; i++)
    get_user(Message[i], buf + i);
    /*
    * we want a standard, zero terminated string
    */
    Message[i] = '\0';

    /*
    * We need to return the number of input characters used
    */
    return i;
    }

    /*
    * 1 if the file is currently open by somebody
    */
    int Already_Open = 0;

    /*
    * Queue of processes who want our file
    */
    DECLARE_WAIT_QUEUE_HEAD(WaitQ);
    /*
    * Called when the /proc file is opened
    */
    static int module_open(struct inode *inode, struct file *file)
    {
    /*
    * If the file's flags include O_NONBLOCK, it means the process doesn't
    * want to wait for the file. In this case, if the file is already
    * open, we should fail with -EAGAIN, meaning "you'll have to try
    * again", instead of blocking a process which would rather stay awake.
    */
    if ((file->f_flags & O_NONBLOCK) && Already_Open)
    return -EAGAIN;

    /*
    * This is the correct place for try_module_get(THIS_MODULE) because
    * if a process is in the loop, which is within the kernel module,
    * the kernel module must not be removed.
    */
    try_module_get(THIS_MODULE);

    /*
    * If the file is already open, wait until it isn't
    */

    while (Already_Open) {
    int i, is_sig = 0;

    /*
    * This function puts the current process, including any system
    * calls, such as us, to sleep. Execution will be resumed right
    * after the function call, either because somebody called
    * wake_up(&WaitQ) (only module_close does that, when the file
    * is closed) or when a signal, such as Ctrl-C, is sent
    * to the process
    */
    wait_event_interruptible(WaitQ, !Already_Open);

    /*
    * If we woke up because we got a signal we're not blocking,
    * return -EINTR (fail the system call). This allows processes
    * to be killed or stopped.
    */

    /*
    * Emmanuel Papirakis:
    *
    * This is a little update to work with 2.2.*. Signals now are contained in
    * two words (64 bits) and are stored in a structure that contains an array of
    * two unsigned longs. We now have to make 2 checks in our if.
    *
    * Ori Pomerantz:
    *
    * Nobody promised me they'll never use more than 64 bits, or that this book
    * won't be used for a version of Linux with a word size of 16 bits. This code
    * would work in any case.
    */
    for (i = 0; i < _NSIG_WORDS && !is_sig; i++)
    is_sig =
    current->pending.signal.sig[i] & ~current->
    blocked.sig[i];

    if (is_sig) {
    /*
    * It's important to put module_put(THIS_MODULE) here,
    * because for processes where the open is interrupted
    * there will never be a corresponding close. If we
    * don't decrement the usage count here, we will be
    * left with a positive usage count which we'll have no
    * way to bring down to zero, giving us an immortal
    * module, which can only be killed by rebooting
    * the machine.
    */
    module_put(THIS_MODULE);
    return -EINTR;
    }
    }

    /*
    * If we got here, Already_Open must be zero
    */

    /*
    * Open the file
    */
    Already_Open = 1;
    return 0; /* Allow the access */
    }

    /*
    * Called when the /proc file is closed
    */
    int module_close(struct inode *inode, struct file *file)
    {
    /*
    * Set Already_Open to zero, so one of the processes in the WaitQ will
    * be able to set Already_Open back to one and to open the file. All
    * the other processes will be called when Already_Open is back to one,
    * so they'll go back to sleep.
    */
    Already_Open = 0;

    /*
    * Wake up all the processes in WaitQ, so if anybody is waiting for the
    * file, they can have it.
    */
    wake_up(&WaitQ);

    module_put(THIS_MODULE);

    return 0; /* success */
    }

    /*
    * This function decides whether to allow an operation (return zero) or not
    * allow it (return a non-zero which indicates why it is not allowed).
    *
    * The operation can be one of the following values:
    * 0 - Execute (run the "file" - meaningless in our case)
    * 2 - Write (input to the kernel module)
    * 4 - Read (output from the kernel module)
    *
    * This is the real function that checks file permissions. The permissions
    * returned by ls -l are for reference only, and can be overridden here.
    */
    static int module_permission(struct inode *inode, int op, struct nameidata *nd)
    {
    /*
    * We allow everybody to read from our module, but only root (uid 0)
    * may write to it
    */
    if (op == 4 || (op == 2 && current->euid == 0))
    return 0;

    /*
    * If it's anything else, access is denied
    */
    return -EACCES;
    }

    /*
    * Structures to register as the /proc file, with pointers to all the relevant
    * functions.
    */

    /*
    * File operations for our proc file. This is where we place pointers to all
    * the functions called when somebody tries to do something to our file. NULL
    * means we don't want to deal with something.
    */
    static struct file_operations File_Ops_4_Our_Proc_File = {
    .read = module_output, /* "read" from the file */
    .write = module_input, /* "write" to the file */
    .open = module_open, /* called when the /proc file is opened */
    .release = module_close, /* called when it's closed */
    };

    /*
    * Inode operations for our proc file. We need it so we'll have somewhere to
    * specify the file operations structure we want to use, and the function we
    * use for permissions. It's also possible to specify functions to be called
    * for anything else which could be done to an inode (although we don't bother,
    * we just put NULL).
    */

    static struct inode_operations Inode_Ops_4_Our_Proc_File = {
    .permission = module_permission, /* check for permissions */
    };

    /*
    * Module initialization and cleanup
    */

    /*
    * Initialize the module - register the proc file
    */

    int init_module()
    {
    int rv = 0;
    Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
    Our_Proc_File->owner = THIS_MODULE;
    Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File;
    Our_Proc_File->proc_fops = &File_Ops_4_Our_Proc_File;
    Our_Proc_File->mode = S_IFREG | S_IRUGO | S_IWUSR;
    Our_Proc_File->uid = 0;
    Our_Proc_File->gid = 0;
    Our_Proc_File->size = 80;

    if (Our_Proc_File == NULL) {
    rv = -ENOMEM;
    remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
    printk(KERN_INFO "Error: Could not initialize /proc/test\n" );
    }

    return rv;
    }

    /*
    * Cleanup - unregister our file from /proc. This could get dangerous if
    * there are still processes waiting in WaitQ, because they are inside our
    * open function, which will get unloaded. I'll explain how to avoid removal
    * of a kernel module in such a case in chapter 10.
    */
    void cleanup_module()
    {
    remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
    }
    Notes
    [1] ×î·½±ãµÄ±£³Öij¸öÎļþ±»´ò¿ªµÄ·½·¨ÊÇʹÓÃÃüÁî tail -f´ò¿ª¸ÃÎļþ¡£

    [2] Õâ¾ÍÒâζןýø³ÌÈÔÈ»ÔÚÄÚºË̬ÖУ¬ ¸Ã½ø³ÌÒѾ­µ÷ÓÃÁËopenµÄϵͳµ÷Ó㬵«ÏµÍ³µ÷ÓÃȴûÓзµ»Ø¡£ ÔÚÕâ¶Îʱ¼äÄڸýø³Ì½«²»»áµÃÖª±ðÈËÕýÔÚʹÓÃCPU¡£

    [3] ÕâÊÇÒòΪÎÒÃÇʹÓõÄÊÇmodule_interruptible_sleep_on¡£ÎÒÃÇÒ²¿ÉÒÔʹÓà module_sleep_on£¬µ«ÕâÑù»áµ¼ÖÂһЩʮ·Ö·ßÅ­µÄÓû§£¬ÒòΪËûÃǵÄCtrl+c½«²»ÆðÈκÎ×÷Óá£

  11. febspeolal ÓÚ 2006-11-09 01:11:01·¢±í:

    Chapter 8. System Calls
    ϵͳµ÷ÓÃ
    µ½Ä¿Ç°ÎªÖ¹£¬ÎÒÃÇËù×öµÄÖ»ÊÇʹÓÃÍêÉƵÄÄں˻úÖÆ×¢²á/procÎļþºÍ´¦ÀíÉ豸µÄ¶ÔÏó¡£Èç¹ûÖ»ÊÇÏëдһ¸öÉ豸Çý¶¯£¬ ÕâЩÄں˳ÌÐòÔ±É趨µÄ·½Ê½ÒѾ­×ã¹»ÁË¡£µ«ÊÇ£¬Äã²»Ïë×öһЩ²»Ñ°³£µÄÊÂÂ𣬠ÏëʹÄãµÄϵͳ¿´ÆðÀ´²»Ò»ÑùÂ𣿵±È»£¬ÕâÈ¡¾öÄã×Ô¼º¡£

    ÕâÀï¿ÉÊÇÒ»¸öΣÏյĵط½¡£ÏÂÃæµÄÕâ¸öÀý×ÓÖУ¬ÎҹرÕÁËϵͳµ÷Óà open()¡£ÕâÒâζ×ÅÎÒÎÞ·¨´ò¿ªÈκÎÎļþ£¬Ö´ÐÐÈκγÌÐò£¬Á¬Ê¹Óà shutdown¹Ø»ú¶¼²»ÐУ¬¹Ø»úÖ»ÄÜ¿¿ÞôµçÔ´°´Å¥ÁË¡£ÐÒÔ˵Ļ°£¬²»»áÓÐÎļþ¶ªÊ§¡£ Òª±£Ö¤²»¶ªÊ§ÎļþµÄ»°£¬ÔÚinsmodºÍ rmmod֮ǰÇëÖ´ÐÐsyncÃüÁî¡£

    ±ð¹Üʲô/procÎļþºÍʲôÉ豸ÎļþÁË£¬ ËüÃÇÖ»ÊÇСµÄϸ½ÚÎÊÌâ¡£ËùÓнø³ÌͬÄں˴ò½»µÀµÄ¸ù±¾·½Ê½ÊÇϵͳµ÷Óᣠµ±Ò»¸ö½ø³ÌÐèÒªÄÚºËÌṩijÏî·þÎñʱ£¨Ïñ´ò¿ªÒ»¸öÎļþ£¬Éú³ÉÒ»¸öнø³Ì£¬»òÒªÇó¸ü¶àµÄÄڴ棩£¬ ¾Í»á·¢Éúϵͳµ÷Óá£Èç¹ûÄãÏëÄãµÄϵͳÔË×÷·½Ê½¿´ÆðÀ´ÓÐÒâ˼µã£¬Õâ¾ÍÊÇÄ㶯Êֵĵط½¡£ ˳±ã˵һ¾ä£¬Èç¹ûÄãÏëÖªµÀû¸ö³ÌÐòʹÓÃÁËÄÄЩϵͳµ÷Óã¬ÔËÐÐstrace ¡£

    ×ܵÄÀ´Ëµ£¬Ò»¸öÓû§½ø³ÌÊDz»Ó¦¸ÃÒ²²»Äܹ»Ö±½Ó·ÃÎÊÄں˵ġ£Ëü²»ÄÜ·ÃÎÊÄں˵ÄÄڴ棬 Ò²²»Äܵ÷ÓÃÄں˵ĺ¯Êý¡£ÕâÊÇCPUµÄÓ²¼þ±£»¤»úÖƾö¶¨µÄ£¨ÕâÒ²ÊÇΪʲô½Ð×ö¡°±£»¤Ä£Ê½¡±µÄÔ­Òò£©¡£

    ϵͳµ÷ÓÃÊÇÕâÌõ¹æÔòµÄÀýÍâ¡£Ëù·¢ÉúµÄÊÂÊÇÒ»¸ö½ø³ÌÓúÏÊʵÄÖµÌî³ä¼Ä´æÆ÷£¬ È»ºóµ÷ÓÃÒ»ÌõÌøתµ½Òѱ»¶¨Òå¹ýµÄÄÚºËÖеÄλÖõÄÖ¸Áµ±È»£¬ÕâЩ¶¨Òå¹ýµÄλÖÃÊǶÔÓÚÓû§½ø³Ì¿É¶ÁµÄ£¬ µ«ÊÇÏÔÈ»ÊDz»¿ÉдµÄ£©¡£ÔÚIntel¼Ü¹¹ÖУ¬ÕâÊÇͨ¹ý 0x80 ÖжÏÍê³ÉµÄ¡£Ó²¼þÃ÷°×Ò»µ©ÄãÌøתµ½Õâ¸öλÖ㬠Äã¾Í²»ÔÙÊÇÔÚ´¦´¦ÊÜÏÞµÄÓû§Ì¬ÖÐÔËÐÐÁË£¬¶øÊÇÔÚÎÞËù²»ÄܵÄÄÚºË̬ÖС£

    ÄÚºËÖеĽø³Ì¿ÉÒÔÌøת¹ýÈ¥µÄλÖýÐ×öϵͳµ÷Óá£ÄǶù½«¼ì²éϵͳµ÷ÓõÄÐòºÅ£¬ ÕâЩÐòºÅ½«¸æËßÄÚºËÓû§½ø³ÌÐèҪʲôÑùµÄ·þÎñ¡£È»ºó£¬Í¨¹ý²éÕÒϵͳµ÷Óñí( sys_call_table) ÕÒµ½Äں˺¯ÊýµÄµØÖ·£¬µ÷Óøú¯Êý¡£µ±º¯Êý·µ»Øʱ£¬ ÔÙ×öһЩϵͳ¼ì²é£¬½Óמͷµ»ØÓû§½ø³Ì£¨»òÊÇÁíÒ»¸ö½ø³Ì£¬Èç¹û¸Ã½ø³ÌµÄʱ¼äÓÃÍêÁË£©¡£ Èç¹ûÄãÏëÔĶÁÒ»ÏÂÕâ·½ÃæµÄÔ´´úÂ룬ËüÃǾÍÔÚÎļþ arch/$<$architecture$>$/kernel/entry.SÖÐ ENTRY(system_call)ÐеÄÏÂÃæ¡£

    ËùÒÔ£¬Èç¹ûÎÒÃÇÏë¸Ä±äij¸öϵͳµ÷ÓõÄÔË×÷·½Ê½£¬ÎÒÃÇÖ»ÐèÒªÓÃÎÒÃÇ×Ô¼ºµÄº¯ÊýȥʵÏÖËü (ͨ³£Ö»ÊǼÓÒ»µãÎÒÃÇ×Ô¼ºµÄ´úÂ룬Ȼºóµ÷ÓÃÔ­º¯Êý)È»ºó¸Ä±äϵͳµ÷Óñí (sys_call_table)ÖеÄÖ¸ÕëֵʹËüÖ¸ÏòÎÒÃǵĺ¯Êý¡£ÒòΪÕâЩģ¿é½«ÔÚÒÔºóжÔØ£¬ ÎÒÃDz»ÏëϵͳÒò´Ë¶ø²»Îȶ¨£¬ËùÒÔcleanup_moduleÖлָ´ÏµÍ³µ÷ÓñíÊǷdz£ÖØÒªµÄ¡£

    Õâ¾ÍÊÇÕâÑùµÄÒ»¸öÄ£¿é¡£ÎÒÃÇ¿ÉÒÔ¡°¼àÊÓ¡±Ò»¸öÌض¨µÄÓû§£¬È»ºóʹÓà printk()Êä³ö¸ÃÓû§´ò¿ªµÄÿ¸öÎļþµÄÏûÏ¢¡£ÔÚ½áÊøÇ°£¬ÎÒÃÇÓÃ×Ô¼ºµÄ our_sys_openº¯ÊýÌæ»»ÁË´ò¿ªÎļþµÄϵͳµ÷Ó᣸ú¯Êý¼ì²éµ±Ç°½ø³ÌµÄÓû§ÐòºÅ£¨uid£¬user's id£©£¬ Èç¹ûÆ¥ÅäÎÒÃǼàÊÓµÄÓû§µÄÐòºÅ£¬Ëüµ÷ÓÃprintk()Êä³ö½«Òª´ò¿ªµÄÎļþµÄÃû×Ö¡£ Òª²»È»£¬¾ÍÓÃͬÑùµÄ²ÎÊýµ÷ÓÃԭʼµÄopen()º¯Êý£¬ÕæÕýµÄ´ò¿ªÎļþ¡£

    º¯Êýinit_module¸Ä±äÁËϵͳµ÷ÓñíÖеÄÇ¡µ±Î»ÖõÄֵȻºóÓÃÒ»¸ö±äÁ¿±£´æÏÂÀ´¡£º¯Êý cleanup_moduleÔòʹÓøñäÁ¿½«ËùÓж«Î÷»¹Ô­¡£ÕâÖÖ´¦Àí·½·¨ÆäʵÊǺÜΣÏյġ£ÏëÏóһϣ¬ Èç¹ûÎÒÃÇÓÐÁ½¸öÕâÑùµÄÄ£¿é£¬AºÍB¡£AÓÃA_openÌæ»»ÁËϵͳµÄsys_openº¯Êý£¬¶øBÓÃB_open¡£ÏÖÔÚ£¬ÎÒÃÇÏÈ°ÑÄ£¿éA¼ÓÔØ£¬ ÄÇôԭÏȵÄϵͳµ÷Óñ»A_openÌæ´úÁË£¬A_openÔÚÍê³É¹¤×÷ºó×ÔÉíÓÖ»áµ÷ÓÃԭʼµÄsys_openº¯Êý ¡£½Ó×Å£¬ÎÒÃǼÓÔØBÄ£¿é£¬ ËüÓÃB_open¸ü¸ÄÁËÏÖÔÚµÄÒѸü¸ÄΪA_open£¨ÏÔÈ»ËüÈÏΪÊÇԭʼµÄsys_openϵͳµ÷Ó㩵Äϵͳµ÷Óá£

    ÏÖÔÚ£¬Èç¹ûBÏÈжÔØ£¬Ò»ÇÐÕý³£¡£ÏµÍ³µ÷Óûỹԭµ½A_open£¬¶øA_openÓÖ»áµ÷ÓÃԭʼµÄsys_open¡£ µ«ÊÇ£¬Ò»µ©AÏÈжÔØ£¬ÏµÍ³¾Í»á±ÀÀ£¡£AµÄжÔػὫϵͳµ÷Óû¹Ô­µ½Ô­Ê¼µÄsys_open£¬°ÑB´ÓÁ´ÖÐÇжϡ£ ´ËʱÔÙжÔØB£¬B»á½«ÏµÍ³µ÷Óûָ´µ½ËüÈÏΪµÄ³õʼ״̬£¬Ò²¾ÍÊÇA_open£¬µ«A_openÒѾ­²»ÔÚÄÚ´æÖÐÁË¡£ Õ§Ò»¿´À´£¬ÎÒÃÇËƺõ¿ÉÒÔͨ¹ý¼ì²âϵͳµ÷ÓÃÊÇ·ñÓëÎÒÃǵÄopenº¯ÊýÏàͬ£¬Èç¹û²»ÏàͬÔòʲô¶¼²»×ö £¨ÕâÑùB¾Í²»»á³¢ÊÔÔÚжÔØʱ»Ö¸´ÏµÍ³µ÷ÓÃ±í£©¡£µ«ÆäʵÕâÑù¸üÔã¡£µ±AÏȱ»Ð¶ÔØʱ£¬Ëü½«¼ì²âµ½ÏµÍ³ µ÷ÓÃÒѱ»¸ü¸ÄΪB_open£¬ËùÒÔA½«²»»áÔÚжÔØʱ»Ö¸´ÏµÍ³µ÷ÓñíÖÐÏàÓ¦µÄÏî¡£´Ëʱ²»ÐÒµÄÊ·¢ÉúÁË£¬ B_open½«ÈÔÈ»µ÷ÓÃÒѾ­²»´æÔÚµÄA_open£¬ÕâÑù¼´Ê¹Ä㲻жÔØBÄ£¿é£¬ÏµÍ³Ò²±ÀÀ£ÁË¡£

    µ«ÊÇÕâÖÖÌ滻ϵͳµ÷Óõķ½·¨ÊÇÎ¥±³ÕýʽӦÓÃÖÐϵͳµÄÎȶ¨ºÍ¿É¿¿Ô­ÔòµÄ¡£ËùÒÔ£¬ÎªÁË·ÀֹDZÔڵĶÔϵͳµ÷Óñí Ð޸ĴøÀ´µÄΣº¦£¬ÏµÍ³µ÷Óñísys_call_table²»ÔÙ±»Äں˵¼³ö¡£ÕâÒâζ×ÅÈç¹ûÄãÏë˳ÀûµÄÔËÐÐÕâ¸öÀý×Ó£¬Äã±ØÐëΪÄãµÄ ÄÚºËÊ÷´ò²¹¶¡À´µ¼³ösys_call_table£¬ÔÚexampleĿ¼ÄÚÄ㽫ÕÒµ½Ïà¹ØµÄ²¹¶¡ºÍ˵Ã÷¡£ÕýÈçͬÄãÏëÏñµÄÄÇÑù£¬Õâ¿É²»ÊÇ ¶ùÏ·£¬Èç¹ûÄãµÄϵͳ·Ç³£±¦¹ó(ÀýÈçÕâ²»ÊÇÄãµÄϵͳ£¬»òϵͳºÜÄѻָ´)£¬Äã×îºÃ»¹ÊÇ·ÅÆú¡£Èç¹ûÄãÈÔÈ»¼á³Ö£¬ÎÒ¿ÉÒÔ ¸æËßÄãµÄÊÇ´ò²¹¶¡ËäÈ»²»»áÓжà´óÎÊÌ⣬µ«ÄÚºËά»¤ÕßËûÃǿ϶¨ÓÐ×ã¹»µÄÀíÓÉÔÚ2.6ÄÚºËÖв»Ö§³ÖÕâÖÖhack¡£ÏêÇéÇë²Î¿¼README¡£ Èç¹ûÄãÑ¡ÔñÁËN£¬Ìø¹ýÕâ¸öÀý×ÓÊÇÒ»¸ö°²È«µÄÑ¡Ôñ¡£

    Example 8-1. syscall.c

    /*
    * syscall.c
    *
    * System call "stealing" sample.
    */

    /*
    * Copyright (C) 2001 by Peter Jay Salzman
    */

    /*
    * The necessary header files
    */

    /*
    * Standard in kernel modules
    */
    #include /* We're doing kernel work */
    #include /* Specifically, a module, */
    #include /* which will have params */
    #include /* The list of system calls */

    /*
    * For the current (process) structure, we need
    * this to know who the current user is.
    */
    #include
    #include

    /*
    * The system call table (a table of functions). We
    * just define this as external, and the kernel will
    * fill it up for us when we are insmod'ed
    *
    * sys_call_table is no longer exported in 2.6.x kernels.
    * If you really want to try this DANGEROUS module you will
    * have to apply the supplied patch against your current kernel
    * and recompile it.
    */
    extern void *sys_call_table[];

    /*
    * UID we want to spy on - will be filled from the
    * command line
    */
    static int uid;
    module_param(uid, int, 0644);

    /*
    * A pointer to the original system call. The reason
    * we keep this, rather than call the original function
    * (sys_open), is because somebody else might have
    * replaced the system call before us. Note that this
    * is not 100% safe, because if another module
    * replaced sys_open before us, then when we're inserted
    * we'll call the function in that module - and it
    * might be removed before we are.
    *
    * Another reason for this is that we can't get sys_open.
    * It's a static variable, so it is not exported.
    */
    asmlinkage int (*original_call) (const char *, int, int);

    /*
    * The function we'll replace sys_open (the function
    * called when you call the open system call) with. To
    * find the exact prototype, with the number and type
    * of arguments, we find the original function first
    * (it's at fs/open.c).
    *
    * In theory, this means that we're tied to the
    * current version of the kernel. In practice, the
    * system calls almost never change (it would wreck havoc
    * and require programs to be recompiled, since the system
    * calls are the interface between the kernel and the
    * processes).
    */
    asmlinkage int our_sys_open(const char *filename, int flags, int mode)
    {
    int i = 0;
    char ch;

    /*
    * Check if this is the user we're spying on
    */
    if (uid == current->uid) {
    /*
    * Report the file, if relevant
    */
    printk("Opened file by %d: ", uid);
    do {
    get_user(ch, filename + i);
    i++;
    printk("%c", ch);
    } while (ch != 0);
    printk("\n" );
    }

    /*
    * Call the original sys_open - otherwise, we lose
    * the ability to open files
    */
    return original_call(filename, flags, mode);
    }

    /*
    * Initialize the module - replace the system call
    */
    int init_module()
    {
    /*
    * Warning - too late for it now, but maybe for
    * next time...
    */
    printk("I'm dangerous. I hope you did a " );
    printk("sync before you insmod'ed me.\n" );
    printk("My counterpart, cleanup_module(), is even" );
    printk("more dangerous. If\n" );
    printk("you value your file system, it will " );
    printk("be \"sync; rmmod\" \n" );
    printk("when you remove this module.\n" );

    /*
    * Keep a pointer to the original function in
    * original_call, and then replace the system call
    * in the system call table with our_sys_open
    */
    original_call = sys_call_table[__NR_open];
    sys_call_table[__NR_open] = our_sys_open;

    /*
    * To get the address of the function for system
    * call foo, go to sys_call_table[__NR_foo].
    */

    printk("Spying on UID:%d\n", uid);

    return 0;
    }

    /*
    * Cleanup - unregister the appropriate file from /proc
    */
    void cleanup_module()
    {
    /*
    * Return the system call back to normal
    */
    if (sys_call_table[__NR_open] != our_sys_open) {
    printk("Somebody else also played with the " );
    printk("open system call\n" );
    printk("The system may be left in " );
    printk("an unstable state.\n" );
    }

    sys_call_table[__NR_open] = original_call;
    }

  12. febspeolal ÓÚ 2006-11-09 01:10:36·¢±í:

    Chapter 7. Talking To Device Files
    ÓëÉ豸Îļþ¶Ô»° (writes and IOCTLs)
    É豸ÎļþÊÇÓÃÀ´´ú±íÏà¶ÔÓ¦µÄÓ²¼þÉ豸¡£¾ø´ó¶àÊýµÄÓ²¼þÉ豸ÊÇÓÃÀ´½øÐÐÊä³öºÍÊäÈë²Ù×÷µÄ£¬ ËùÒÔÔÚÄÚºËÖп϶¨ÓÐÄں˴ӽø³ÌÖлñµÃ·¢Ë͵½É豸µÄÊä³öµÄ»úÖÆ¡£ÕâÊÇͨ¹ý´ò¿ªÒ»¸öÉ豸ÎļþÈ»ºó ÏòÆäÖнøÐÐд²Ù×÷À´ÊµÏֵģ¬Èçͬ¶ÔÆÕͨÎļþµÄд²Ù×÷¡£ÔÚÏÂÃæµÄµÄÀý×ÓÖУ¬ÕâÊÇͨ¹ý device_writeʵÏֵġ£

    µ«Õâ²¢²»×ÜÊǹ»Óá£ÉèÏëÄãÓÐÒ»¸öͨ¹ý´®¿ÚÁ¬½ÓµÄµ÷Öƽâµ÷Æ÷(¼´Ê¹ÄãʹÓõÄÊÇÄÚÖõ÷Öƽâµ÷Æ÷£¬ ¶ÔÓÚCPUÀ´ËµÍ¬ÑùÒ²ÊÇͨ¹ýÁ¬½ÓÔÚ´®¿ÚÉÏÀ´ÊµÏÖ¹¤×÷µÄ£©¡£Í¨³£ÎÒÃÇͨ¹ý´ò¿ªÒ»¸öÉ豸ÎļþÏòµ÷Öƽâµ÷Æ÷ ·¢ËÍÐÅÏ¢£¨½«ÒªÍ¨¹ýͨÐÅÏß·´«ÊäµÄÖ¸Áî»òÊý¾Ý£©»ò¶ÁÈ¡ÐÅÏ¢£¨´ÓͨÐÅÏß·Öзµ»ØµÄÏìÓ¦Ö¸Áî»òÊý¾Ý£©¡£ µ«ÊÇ£¬ÎÒÃÇÈçºÎÉèÖÃͬ´®¿Ú¶Ô»°µÄËÙÂÊ£¬Ò²¾ÍÊÇÏò´®¿Ú´«ÊäÊý¾ÝµÄËÙÂÊÕâ¸öÎÊÌâÈÔȻûÓнâ¾ö¡£

    ½â¾öÖ®µÀÊÇÔÚUnixϵͳÖеĺ¯Êýioctl(Input Output ConTroLµÄ¼òд)¡£ ÿ¸öÉ豸¿ÉÒÔÓÐ×Ô¼ºµÄioctlÃüÁͨ¹ý¶ÁÈ¡ioctl's ¿ÉÒÔ´Ó½ø³ÌÖÐÏòÄں˷¢ËÍÐÅÏ¢£¬»òдioctl'sÏò½ø³Ì·µ»ØÐÅÏ¢ [1]£¬»òÕßÁ½Õ߶¼ÊÇ£¬»ò¶¼²»ÊÇ¡£º¯Êýioctl µ÷ÓÃʱÐèÒªÈý¸ö²ÎÊý£ººÏÊʵÄÉ豸ÎļþµÄÎļþÃèÊö·û£¬ioctlºÅ£¬ºÍÒ»¸ö¿ÉÒÔ±»Ò»¸öÈÎÎñʹÓÃÀ´ ´«µÝÈκζ«Î÷µÄlongÀàÐ͵IJÎÊý[2]

    ioctlºÅÊÇ·´Ó³Ö÷É豸ºÅ£¬ioctlµÄÖÖÀ࣬¶ÔÓ¦µÄÃüÁîºÍ²ÎÊýÀàÐ͵ÄÊý×Ö¡£Ëüͨ³£ÊÇͨ¹ýÔÚÍ·ÎļþÖкêµ÷Óà (_IO, _IOR, _IOW »ò_IOWR£¬È¡¾öÓÚÆäÖÖÀà)À´½¨Á¢µÄ¡£¸ÃÍ·ÎļþÓ¦¸Ã±»Ê¹Óà ioctlµÄÓû§³ÌÐò°üº¬£¨ÕâÑùËüÃǾͿÉÒÔÉú³ÉÕýÈ·µÄioctl's£© ºÍÄÚºËÇý¶¯Ä£¿é°üº¬£¨ÕâÑùÄ£¿é²ÅÄÜÀí½âËü£©¡£ÔÚÏÂÃæµÄÀý×ÓÖУ¬Í·ÎļþΪchardev.h£¬Ô´³ÌÐòΪioctl.c¡£

    ¼´Ê¹ÄãÖ»ÏëÔÚ×Ô¼ºµÄÄ£¿éÖÐʹÓÃioctls£¬Äã×îºÃ»¹ÊǽÓÊÕÕýʽµÄ ioctl±ê×¼£¬ÕâÑùµ±ÄãÒâÍâµÄʹÓñðÈ˵Äioctls£¬ »ò±ðÈËʹÓÃÄãµÄʱ£¬Äã»áÖªµÀÓдíÎó·¢Éú¡£ÏêÇé²Î¼ûÄں˴úÂëĿ¼Ê÷ϵÄÎļþ Documentation/ioctl-number.txt.

    Example 7-1. chardev.c

    /*
    * chardev.c - Create an input/output character device
    */

    #include /* We're doing kernel work */
    #include /* Specifically, a module */
    #include
    #include /* for get_user and put_user */

    #include "chardev.h"
    #define SUCCESS 0
    #define DEVICE_NAME "char_dev"
    #define BUF_LEN 80

    /*
    * Is the device open right now? Used to prevent
    * concurent access into the same device
    */
    static int Device_Open = 0;

    /*
    * The message the device will give when asked
    */
    static char Message[BUF_LEN];

    /*
    * How far did the process reading the message get?
    * Useful if the message is larger than the size of the
    * buffer we get to fill in device_read.
    */
    static char *Message_Ptr;

    /*
    * This is called whenever a process attempts to open the device file
    */
    static int device_open(struct inode *inode, struct file *file)
    {
    #ifdef DEBUG
    printk("device_open(%p)\n", file);
    #endif

    /*
    * We don't want to talk to two processes at the same time
    */
    if (Device_Open)
    return -EBUSY;

    Device_Open++;
    /*
    * Initialize the message
    */
    Message_Ptr = Message;
    try_module_get(THIS_MODULE);
    return SUCCESS;
    }

    static int device_release(struct inode *inode, struct file *file)
    {
    #ifdef DEBUG
    printk("device_release(%p,%p)\n", inode, file);
    #endif

    /*
    * We're now ready for our next caller
    */
    Device_Open--;

    module_put(THIS_MODULE);
    return SUCCESS;
    }

    /*
    * This function is called whenever a process which has already opened the
    * device file attempts to read from it.
    */
    static ssize_t device_read(struct file *file, /* see include/linux/fs.h */
    char __user * buffer, /* buffer to be
    * filled with data */
    size_t length, /* length of the buffer */
    loff_t * offset)
    {
    /*
    * Number of bytes actually written to the buffer
    */
    int bytes_read = 0;

    #ifdef DEBUG
    printk("device_read(%p,%p,%d)\n", file, buffer, length);
    #endif

    /*
    * If we're at the end of the message, return 0
    * (which signifies end of file)
    */
    if (*Message_Ptr == 0)
    return 0;

    /*
    * Actually put the data into the buffer
    */
    while (length && *Message_Ptr) {

    /*
    * Because the buffer is in the user data segment,
    * not the kernel data segment, assignment wouldn't
    * work. Instead, we have to use put_user which
    * copies data from the kernel data segment to the
    * user data segment.
    */
    put_user(*(Message_Ptr++), buffer++);
    length--;
    bytes_read++;
    }

    #ifdef DEBUG
    printk("Read %d bytes, %d left\n", bytes_read, length);
    #endif

    /*
    * Read functions are supposed to return the number
    * of bytes actually inserted into the buffer
    */
    return bytes_read;
    }

    /*
    * This function is called when somebody tries to
    * write into our device file.
    */
    static ssize_t
    device_write(struct file *file,
    const char __user * buffer, size_t length, loff_t * offset)
    {
    int i;

    #ifdef DEBUG
    printk("device_write(%p,%s,%d)", file, buffer, length);
    #endif

    for (i = 0; i < length && i < BUF_LEN; i++)
    get_user(Message[i], buffer + i);

    Message_Ptr = Message;

    /*
    * Again, return the number of input characters used
    */
    return i;
    }

    /*
    * This function is called whenever a process tries to do an ioctl on our
    * device file. We get two extra parameters (additional to the inode and file
    * structures, which all device functions get): the number of the ioctl called
    * and the parameter given to the ioctl function.
    *
    * If the ioctl is write or read/write (meaning output is returned to the
    * calling process), the ioctl call returns the output of this function.
    *
    */
    int device_ioctl(struct inode *inode, /* see include/linux/fs.h */
    struct file *file, /* ditto */
    unsigned int ioctl_num, /* number and param for ioctl */
    unsigned long ioctl_param)
    {
    int i;
    char *temp;
    char ch;

    /*
    * Switch according to the ioctl called
    */
    switch (ioctl_num) {
    case IOCTL_SET_MSG:
    /*
    * Receive a pointer to a message (in user space) and set that
    * to be the device's message. Get the parameter given to
    * ioctl by the process.
    */
    temp = (char *)ioctl_param;

    /*
    * Find the length of the message
    */
    get_user(ch, temp);
    for (i = 0; ch && i < BUF_LEN; i++, temp++)
    get_user(ch, temp);

    device_write(file, (char *)ioctl_param, i, 0);
    break;

    case IOCTL_GET_MSG:
    /*
    * Give the current message to the calling process -
    * the parameter we got is a pointer, fill it.
    */
    i = device_read(file, (char *)ioctl_param, 99, 0);

    /*
    * Put a zero at the end of the buffer, so it will be
    * properly terminated
    */
    put_user('\0', (char *)ioctl_param + i);
    break;

    case IOCTL_GET_NTH_BYTE:
    /*
    * This ioctl is both input (ioctl_param) and
    * output (the return value of this function)
    */
    return Message[ioctl_param];
    break;
    }

    return SUCCESS;
    }

    /* Module Declarations */

    /*
    * This structure will hold the functions to be called
    * when a process does something to the device we
    * created. Since a pointer to this structure is kept in
    * the devices table, it can't be local to
    * init_module. NULL is for unimplemented functions.
    */
    struct file_operations Fops = {
    .read = device_read,
    .write = device_write,
    .ioctl = device_ioctl,
    .open = device_open,
    .release = device_release, /* a.k.a. close */
    };

    /*
    * Initialize the module - Register the character device
    */
    int init_module()
    {
    int ret_val;
    /*
    * Register the character device (atleast try)
    */
    ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);

    /*
    * Negative values signify an error
    */
    if (ret_val < 0) {
    printk("%s failed with %d\n",
    "Sorry, registering the character device ", ret_val);
    return ret_val;
    }

    printk("%s The major device number is %d.\n",
    "Registeration is a success", MAJOR_NUM);
    printk("If you want to talk to the device driver,\n" );
    printk("you'll have to create a device file. \n" );
    printk("We suggest you use:\n" );
    printk("mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);
    printk("The device file name is important, because\n" );
    printk("the ioctl program assumes that's the\n" );
    printk("file you'll use.\n" );

    return 0;
    }

    /*
    * Cleanup - unregister the appropriate file from /proc
    */
    void cleanup_module()
    {
    int ret;

    /*
    * Unregister the device
    */
    ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);

    /*
    * If there's an error, report it
    */
    if (ret < 0)
    printk("Error in module_unregister_chrdev: %d\n", ret);
    }
    Example 7-2. chardev.h

    /*
    * chardev.h - the header file with the ioctl definitions.
    *
    * The declarations here have to be in a header file, because
    * they need to be known both to the kernel module
    * (in chardev.c) and the process calling ioctl (ioctl.c)
    */

    #ifndef CHARDEV_H
    #define CHARDEV_H

    #include

    /*
    * The major device number. We can't rely on dynamic
    * registration any more, because ioctls need to know
    * it.
    */
    #define MAJOR_NUM 100

    /*
    * Set the message of the device driver
    */
    #define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
    /*
    * _IOR means that we're creating an ioctl command
    * number for passing information from a user process
    * to the kernel module.
    *
    * The first arguments, MAJOR_NUM, is the major device
    * number we're using.
    *
    * The second argument is the number of the command
    * (there could be several with different meanings).
    *
    * The third argument is the type we want to get from
    * the process to the kernel.
    */

    /*
    * Get the message of the device driver
    */
    #define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
    /*
    * This IOCTL is used for output, to get the message
    * of the device driver. However, we still need the
    * buffer to place the message in to be input,
    * as it is allocated by the process.
    */

    /*
    * Get the n'th byte of the message
    */
    #define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
    /*
    * The IOCTL is used for both input and output. It
    * receives from the user a number, n, and returns
    * Message[n].
    */

    /*
    * The name of the device file
    */
    #define DEVICE_FILE_NAME "char_dev"

    #endif
    Example 7-3. ioctl.c

    /*
    * ioctl.c - the process to use ioctl's to control the kernel module
    *
    * Until now we could have used cat for input and output. But now
    * we need to do ioctl's, which require writing our own process.
    */

    /*
    * device specifics, such as ioctl numbers and the
    * major device file.
    */
    #include "chardev.h"

    #include /* open */
    #include /* exit */
    #include /* ioctl */

    /*
    * Functions for the ioctl calls
    */

    ioctl_set_msg(int file_desc, char *message)
    {
    int ret_val;

    ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);

    if (ret_val < 0) {
    printf("ioctl_set_msg failed:%d\n", ret_val);
    exit(-1);
    }
    }

    ioctl_get_msg(int file_desc)
    {
    int ret_val;
    char message[100];

    /*
    * Warning - this is dangerous because we don't tell
    * the kernel how far it's allowed to write, so it
    * might overflow the buffer. In a real production
    * program, we would have used two ioctls - one to tell
    * the kernel the buffer length and another to give
    * it the buffer to fill
    */
    ret_val = ioctl(file_desc, IOCTL_GET_MSG, message);

    if (ret_val < 0) {
    printf("ioctl_get_msg failed:%d\n", ret_val);
    exit(-1);
    }

    printf("get_msg message:%s\n", message);
    }

    ioctl_get_nth_byte(int file_desc)
    {
    int i;
    char c;

    printf("get_nth_byte message:" );

    i = 0;
    while (c != 0) {
    c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);

    if (c < 0) {
    printf
    ("ioctl_get_nth_byte failed at the %d'th byte:\n",
    i);
    exit(-1);
    }

    putchar(c);
    }
    putchar('\n');
    }

    /*
    * Main - Call the ioctl functions
    */
    main()
    {
    int file_desc, ret_val;
    char *msg = "Message passed by ioctl\n";

    file_desc = open(DEVICE_FILE_NAME, 0);
    if (file_desc < 0) {
    printf("Can't open device file: %s\n", DEVICE_FILE_NAME);
    exit(-1);
    }

    ioctl_get_nth_byte(file_desc);
    ioctl_get_msg(file_desc);
    ioctl_set_msg(file_desc, msg);

    close(file_desc);
    }
    Notes
    [1] ×¢ÒâÕâ¶ù¡°¶Á¡±Ó롰д¡±µÄ½ÇÉ«Ôٴη­×ª¹ýÀ´£¬ÔÚioctl'sÖжÁÊÇÏòÄں˷¢ËÍÐÅÏ¢£¬ ¶øдÊÇ´ÓÄں˻ñÈ¡ÐÅÏ¢¡£

    [2] ÕâÑùµÄ±íÊö²¢²»×¼È·¡£ ÀýÈçÄã²»ÄÜÔÚioctlÖд«µÝÒ»¸ö½á¹¹Ì壬µ«Äã¿ÉÒÔͨ¹ý´«µÝÖ¸ÏòÕâ¸ö½á¹¹ÌåµÄÖ¸ÕëʵÏÖ¡£

  13. febspeolal ÓÚ 2006-11-09 01:10:11·¢±í:

    Chapter 6. Using /proc For Input
    ʹÓà /proc ×÷ΪÊäÈë
    ÏÖÔÚÎÒÃÇÓÐÁ½ÖÖ´ÓÄÚºËÄ£¿é»ñµÃÊä³öµÄ·½·¨£ºÎÒÃÇ¿ÉÒÔ×¢²áÒ»¸öÉ豸Çý¶¯²¢Óà mknodÉú³ÉÒ»¸öÉ豸Îļþ£¬»òÕßÎÒÃÇ¿ÉÒÔ½¨Á¢Ò»¸ö /procÎļþ¡£ÕâÑùÄں˾ͿÉÒÔ¸æËßÎÒÃÇÖØÒªµÄÐÅÏ¢¡£ ʣϵÄΨһÎÊÌâÊÇÎÒÃÇû·¨·´À¡ÐÅÏ¢¡£µÚÒ»ÖÖ·½·¨ÊÇÏò/procÎļþϵͳдÈëÐÅÏ¢¡£

    ÓÉÓÚ /proc ÎļþϵͳÊÇΪÄÚºËÊä³öÆäÔËÐÐÐÅÏ¢¶øÉè¼ÆµÄ£¬Ëü²¢Î´ÏòÄÚºËÊäÈëÐÅÏ¢ÌṩÁËÈκÎ×¼±¸¡£ ½á¹¹Ìåstruct proc_dir_entry²¢Ã»ÓÐÖ¸ÏòÊäÈ뺯ÊýµÄÖ¸Õ룬¶øÊÇÖ¸ÏòÁËÒ»¸öÊä³öº¯Êý¡£ ×÷ΪÌæ´ú°ì·¨£¬Ïò/proc дÈëÐÅÏ¢£¬ÎÒÃÇ¿ÉÒÔʹÓñê×¼µÄÎļþϵͳÌṩµÄ»úÖÆ¡£

    ÔÚLinuxÖÐÓÐÒ»ÖÖ±ê×¼µÄ×¢²áÎļþϵͳµÄ·½·¨¡£¼ÈȻÿÖÖÎļþϵͳ¶¼±ØÐëÓд¦ÀíÎļþ Ë÷Òý½ÚµãinodeºÍÎļþ±¾ÉíµÄº¯Êý[1], ÄÇô¾ÍÒ»¶¨ÓÐÖֽṹÌåÈ¥´æ·ÅÕâЩº¯ÊýµÄÖ¸Õë¡£Õâ¾ÍÊǽṹÌåstruct inode_operations£¬ ËüÆäÖÐÓÖ°üº¬Ò»¸öÖ¸Ïò½á¹¹Ìåstruct file_operationsµÄÖ¸Õë¡£ÔÚ /proc ÎļþϵͳÖУ¬ µ±ÎÒÃÇÐèҪע²áÒ»¸öÐÂÎļþʱ£¬ÎÒÃDZ»ÔÊÐíÑ¡ÔñÄÄÒ»¸östruct inode_operations ½á¹¹Ìå¡£Õâ¾ÍÊÇÎÒÃǽ«Ê¹ÓõĻúÖÆ£¬Óðüº¬½á¹¹Ìå struct inode_operationsÖ¸ÕëµÄ½á¹¹Ìåstruct file_operations À´Ö¸ÏòÎÒÃǵÄmodule_inputºÍmodule_outputº¯Êý¡£

    ÐèҪעÒâµÄÊÇ¡°¶Á¡±ºÍ¡°Ð´¡±µÄº¬ÒåÔÚÄÚºËÖÐÊÇ·´¹ýÀ´µÄ¡£¡°¶Á¡±Òâζ×ÅÊä³ö£¬¶ø¡°Ð´¡±Òâζ×ÅÊäÈë¡£ ÕâÊÇ´ÓÓû§µÄ½Ç¶ÈÀ´¿´´ýÎÊÌâµÄ¡£Èç¹ûÒ»¸ö½ø³ÌÖ»ÄÜ´ÓÄں˵ġ°Êä³ö¡±»ñµÃÊäÈ룬 ¶øÄÚºËÒ²ÊÇ´Ó½ø³ÌµÄÊä³öÖеõ½¡°ÊäÈ롱µÄ¡£

    ÔÚÕâ¶ùÁíÒ»¼þÓÐȤµÄʾÍÊÇmodule_permissionº¯ÊýÁË¡£¸Ãº¯ÊýÔÚÿ¸ö½ø³ÌÏëÒª¶Ô /procÎļþϵͳÄÚµÄÎļþ²Ù×÷ʱ±»µ÷Óã¬ËüÀ´¾ö¶¨ÊÇ·ñ²Ù×÷±»ÔÊÐí¡£ Ä¿Ç°ËüÖ»ÊǶԲÙ×÷ºÍ²Ù×÷ËùÊôÓû§µÄUID½øÐÐÅжϣ¬µ«Ëü¿ÉÒÔÒ²°ÑÆäËüµÄ¶«Î÷°üÀ¨½øÀ´£¬ Ïñ»¹ÓÐÄÄЩ±ðµÄ½ø³ÌÔÚ¶Ô¸ÃÎļþ½øÐвÙ×÷£¬µ±Ç°µÄʱ¼ä£¬»òÊÇÎÒÃÇ×îºó½ÓÊÕµ½µÄÊäÈë¡£

    ¼ÓÈëºêput_userºÍget_userµÄÔ­ÒòÊÇ LinuxµÄÄÚ´æÊÇʹÓ÷ÖÒ³»úÖƵģ¨ÔÚIntel¼Ü¹¹ÏÂÊÇÈç´Ë£¬µ«ÆäËü¼Ü¹¹ÏÂÓпÉÄܲ»Í¬£©¡£ Õâ¾ÍÒâζ×ÅÖ¸Õë×ÔÉí²¢²»ÊÇÖ¸ÏòÒ»¸öȷʵµÄÎïÀíÄÚ´æµØÖ·£¬¶øÖªÊÇ·ÖÒ³ÖеÄÒ»¸öµØÖ·£¬ ¶øÇÒÄã±ØÐëÖªµÀÄÄЩ·ÖÒ³½«À´ÊÇ¿ÉÓõġ£ÆäÖÐÄں˱¾ÉíÕ¼ÓÃÒ»¸ö·ÖÒ³£¬ÆäËüµÄÿ¸ö½ø³Ì¶¼ÓÐ×Ô¼ºµÄ·ÖÒ³¡£

    ½ø³ÌÄÜ¿´µÃµ½µÄ·ÖÒ³Ö»ÓÐÊôÓÚËü×Ô¼ºµÄ£¬ËùÒÔµ±±àдÓû§³ÌÐòʱ£¬²»Óÿ¼ÂÇ·ÖÒ³µÄ´æÔÚ¡£ µ«Êǵ±Äã±àдÄÚºËÄ£¿éʱ£¬Äã¾Í»á·ÃÎÊÓÉϵͳ×Ô¶¯¹ÜÀíµÄÄÚºËËùÔڵķÖÒ³¡£ µ±Ò»¿éÄڴ滺³åÇøÖеÄÄÚÈÝÒªÔÚµ±Ç°ÔËÐÐÖеĽø³ÌºÍÄÚºËÖ®¼ä´«µÝʱ£¬ Äں˵ĺ¯Êý¾Í½ÓÊÕÖ¸ÏòÔÚ½ø³Ì·ÖÒ³ÖеĸÃÄڴ滺³åÇøµÄÖ¸Õë¡£ºêput_userºÍ get_userÔÊÐíÄã½øÐÐÕâÑùµÄ·ÃÎÊÄÚ´æµÄ²Ù×÷¡£

    Example 6-1. procfs.c

    /*
    * procfs.c - create a "file" in /proc, which allows both input and output.
    */
    #include /* We're doing kernel work */
    #include /* Specifically, a module */
    #include /* Necessary because we use proc fs */
    #include /* for get_user and put_user */

    /*
    * Here we keep the last message received, to prove
    * that we can process our input
    */
    #define MESSAGE_LENGTH 80
    static char Message[MESSAGE_LENGTH];
    static struct proc_dir_entry *Our_Proc_File;

    #define PROC_ENTRY_FILENAME "rw_test"

    static ssize_t module_output(struct file *filp, /* see include/linux/fs.h */
    char *buffer, /* buffer to fill with data */
    size_t length, /* length of the buffer */
    loff_t * offset)
    {
    static int finished = 0;
    int i;
    char message[MESSAGE_LENGTH + 30];

    /*
    * We return 0 to indicate end of file, that we have
    * no more information. Otherwise, processes will
    * continue to read from us in an endless loop.
    */
    if (finished) {
    finished = 0;
    return 0;
    }

    /*
    * We use put_user to copy the string from the kernel's
    * memory segment to the memory segment of the process
    * that called us. get_user, BTW, is
    * used for the reverse.
    */
    sprintf(message, "Last input:%s", Message);
    for (i = 0; i < length && message[i]; i++)
    put_user(message[i], buffer + i);

    /*
    * Notice, we assume here that the size of the message
    * is below len, or it will be received cut. In a real
    * life situation, if the size of the message is less
    * than len then we'd return len and on the second call
    * start filling the buffer with the len+1'th byte of
    * the message.
    */
    finished = 1;

    return i; /* Return the number of bytes "read" */
    }

    static ssize_t
    module_input(struct file *filp, const char *buff, size_t len, loff_t * off)
    {
    int i;
    /*
    * Put the input into Message, where module_output
    * will later be able to use it
    */
    for (i = 0; i < MESSAGE_LENGTH - 1 && i < len; i++)
    get_user(Message[i], buff + i);

    Message[i] = '\0'; /* we want a standard, zero terminated string */
    return i;
    }

    /*
    * This function decides whether to allow an operation
    * (return zero) or not allow it (return a non-zero
    * which indicates why it is not allowed).
    *
    * The operation can be one of the following values:
    * 0 - Execute (run the "file" - meaningless in our case)
    * 2 - Write (input to the kernel module)
    * 4 - Read (output from the kernel module)
    *
    * This is the real function that checks file
    * permissions. The permissions returned by ls -l are
    * for referece only, and can be overridden here.
    */

    static int module_permission(struct inode *inode, int op, struct nameidata *foo)
    {
    /*
    * We allow everybody to read from our module, but
    * only root (uid 0) may write to it
    */
    if (op == 4 || (op == 2 && current->euid == 0))
    return 0;

    /*
    * If it's anything else, access is denied
    */
    return -EACCES;
    }

    /*
    * The file is opened - we don't really care about
    * that, but it does mean we need to increment the
    * module's reference count.
    */
    int module_open(struct inode *inode, struct file *file)
    {
    try_module_get(THIS_MODULE);
    return 0;
    }

    /*
    * The file is closed - again, interesting only because
    * of the reference count.
    */
    int module_close(struct inode *inode, struct file *file)
    {
    module_put(THIS_MODULE);
    return 0; /* success */
    }

    static struct file_operations File_Ops_4_Our_Proc_File = {
    .read = module_output,
    .write = module_input,
    .open = module_open,
    .release = module_close,
    };

    /*
    * Inode operations for our proc file. We need it so
    * we'll have some place to specify the file operations
    * structure we want to use, and the function we use for
    * permissions. It's also possible to specify functions
    * to be called for anything else which could be done to
    * an inode (although we don't bother, we just put
    * NULL).
    */

    static struct inode_operations Inode_Ops_4_Our_Proc_File = {
    .permission = module_permission, /* check for permissions */
    };

    /*
    * Module initialization and cleanup
    */
    int init_module()
    {
    int rv = 0;
    Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
    Our_Proc_File->owner = THIS_MODULE;
    Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File;
    Our_Proc_File->proc_fops = &File_Ops_4_Our_Proc_File;
    Our_Proc_File->mode = S_IFREG | S_IRUGO | S_IWUSR;
    Our_Proc_File->uid = 0;
    Our_Proc_File->gid = 0;
    Our_Proc_File->size = 80;

    if (Our_Proc_File == NULL) {
    rv = -ENOMEM;
    remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
    printk(KERN_INFO "Error: Could not initialize /proc/test\n");
    }

    return rv;
    }

    void cleanup_module()
    {
    remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
    }
    »¹ÐèÒª¸ü¶àµÄ¹ØÓÚprocfsµÄÀý×Ó£¿ÎÒÒªÌáÐÑÄãµÄÊÇ£ºµÚÒ»£¬ÓÐÏûϢ˵ҲÐí²»¾Ãprocfs½«±»sysfsÈ¡´ú£»µÚ¶þ£¬ Èç¹ûÄãÕæµÄºÜÏë¶àÁ˽âЩprocfs£¬Äã¿ÉÒԲο¼Â·¾¶ linux/Documentation/DocBook/ Ï嵀 ÄÇЩ¼¼ÊõÐÔµÄÎĵµ¡£ÔÚÄں˴úÂëÊ÷¸ùĿ¼ÏÂʹÓà make help À´»ñµÃÈçºÎ½«ÕâЩÎĵµ×ª»¯ÎªÄãÆ«ºÃµÄ¸ñʽ£¬ÀýÈ磺 make htmldocs ¡£Èç¹ûÄãҪΪÄں˼ÓÈëһЩÄãµÄÎĵµ£¬ÄãÒ²Ó¦¸Ã¿¼ÂÇÕâÑù×ö¡£

    Notes
    [1] Á½ÕßµÄÇø±ðÊÇÎļþµÄ²Ù×÷Õë¶Ô¾ßÌåµÄ£¬ÊµÔÚµÄÎļþ£¬ ¶øÎļþË÷Òý½ÚµãµÄ²Ù×÷ÊÇÕë¶ÔÎļþµÄÒýÓã¬Ïñ½¨Á¢ÎļþµÄÁ¬½ÓµÈ¡£

  14. febspeolal ÓÚ 2006-11-09 01:09:35·¢±í:

    Chapter 5. The /proc File System
    ¹ØÓÚ /proc Îļþϵͳ
    ÔÚLinuxÖÐÓÐÁíÒ»ÖÖÄں˺ÍÄÚºËÄ£¿éÏò½ø³Ì´«µÝÐÅÏ¢µÄ·½·¨£¬ÄǾÍÊÇͨ¹ý /procÎļþϵͳ¡£ËüÔ­ÏÈÉè¼ÆµÄÄ¿µÄÊÇΪ²é¿´½ø³ÌÐÅÏ¢ Ìṩһ¸ö·½±ãµÄ;¾¶£¬ÏÖÔÚËü±»ÓÃÀ´ÏòÓû§Ìṩ¸÷ÖÖÄÚºËÖб»¸ÐÐËȤµÄÄÚÈÝ¡£ÏñÎļþ /proc/modulesÀïÊÇÒѼÓÔØÄ£¿éµÄÁÐ±í£¬Îļþ/proc/meminfo ÀïÊǹØÓÚÄÚ´æʹÓõÄÐÅÏ¢¡£

    ʹÓà proc ÎļþϵͳµÄ·½·¨Í¬Ê¹ÓÃÉ豸ÎļþºÜÏàËÆ¡£Ä㽨Á¢Ò»¸ö°üº¬ /procÎļþÐèÒªµÄËùÓÐÐÅÏ¢µÄ½á¹¹Ì壬 ÕâÆäÖаüÀ¨´¦Àí¸÷ÖÖÊÂÎñµÄº¯ÊýµÄÖ¸Õ루ÔÚÎÒÃǵÄÀý×ÓÖУ¬Ö»Óõ½´Ó/procÎļþ¶ÁÈ¡ÐÅÏ¢µÄº¯Êý£©¡£È»ºóÔÚinit_module ʱÏòÄÚºË×¢²áÕâ¸ö½á¹¹Ì壬ÔÚcleanup_moduleʱעÏúÕâ¸ö½á¹¹Ìå¡£

    ÎÒÃÇʹÓÃproc_register_dynamic[1]µÄÔ­ÒòÊÇÎÒÃDz»ÓÃÈ¥ÉèÖÃinode£¬¶øÁô¸ø ÄÚºËÈ¥×Ô¶¯·ÖÅä´Ó¶ø±ÜÃâϵͳ³åÍ»´íÎó¡£ ÆÕͨµÄÎļþϵͳÊǽ¨Á¢ÔÚ´ÅÅÌÉϵģ¬¶ø /proc µÄÎļþ½ö½öÊǽ¨Á¢ÔÚÄÚ´æÖеġ£ ÔÚÇ°ÖÖÇé¿öÖУ¬inodeµÄÊýÖµÊÇÒ»¸öÖ¸Ïò´æ´¢ÔÚ´ÅÅÌij¸öλÖõÄÎļþµÄË÷Òý½Úµã£¨inode¾ÍÊÇindex-nodeµÄËõд£©¡£ ¸ÃË÷Òý½Úµã´¢´æ×ÅÎļþµÄÐÅÏ¢£¬ÏñÎļþµÄȨÏÞ£»Í¬Ê±»¹ÓÐÔÚÄĶùÄÜÕÒµ½ÎļþÖеÄÊý¾Ý¡£

    ÒòΪÎÒÃÇÎÞ·¨µÃÖª¸ÃÎļþÊDZ»´ò¿ªµÄ»ò¹Ø±ÕµÄ£¬ÎÒÃÇÒ²ÎÞ·¨È¥Ê¹Óúê try_module_getºÍtry_module_putÔÚÏÂÃæµÄÄ£¿éÖУ¬ ÎÒÃÇÎÞ·¨±ÜÃâ¸ÃÎļþ±»´ò¿ª¶øͬʱģ¿éÓÖ±»Ð¶ÔØ¡£ÔÚÏÂÕÂÖÐÎÒ½«½éÉÜÒ»¸ö½ÏÄÑʵÏÖ£¬È´¸üÁé»î£¬¸ü°²È«µÄ´¦Àí /procÎļþµÄ·½·¨¡£

    Example 5-1. procfs.c

    /*
    * procfs.c - create a "file" in /proc
    */

    #include /* Specifically, a module */
    #include /* We're doing kernel work */
    #include /* Necessary because we use the proc fs */

    struct proc_dir_entry *Our_Proc_File;

    /* Put data into the proc fs file.
    *
    * Arguments
    * =========
    * 1. The buffer where the data is to be inserted, if
    * you decide to use it.
    * 2. A pointer to a pointer to characters. This is
    * useful if you don't want to use the buffer
    * allocated by the kernel.
    * 3. The current position in the file
    * 4. The size of the buffer in the first argument.
    * 5. Write a "1" here to indicate EOF.
    * 6. A pointer to data (useful in case one common
    * read for multiple /proc/... entries)
    *
    * Usage and Return Value
    * ======================
    * A return value of zero means you have no further
    * information at this time (end of file). A negative
    * return value is an error condition.
    *
    * For More Information
    * ====================
    * The way I discovered what to do with this function
    * wasn't by reading documentation, but by reading the
    * code which used it. I just looked to see what uses
    * the get_info field of proc_dir_entry struct (I used a
    * combination of find and grep, if you're interested),
    * and I saw that it is used in * directory>/fs/proc/array.c.
    *
    * If something is unknown about the kernel, this is
    * usually the way to go. In Linux we have the great
    * advantage of having the kernel source code for
    * free - use it.
    */
    ssize_t
    procfile_read(char *buffer,
    char **buffer_location,
    off_t offset, int buffer_length, int *eof, void *data)
    {
    printk(KERN_INFO "inside /proc/test : procfile_read\n" );

    int len = 0; /* The number of bytes actually used */
    static int count = 1;

    /*
    * We give all of our information in one go, so if the
    * user asks us if we have more information the
    * answer should always be no.
    *
    * This is important because the standard read
    * function from the library would continue to issue
    * the read system call until the kernel replies
    * that it has no more information, or until its
    * buffer is filled.
    */
    if (offset > 0) {
    printk(KERN_INFO "offset %d : /proc/test : procfile_read, \
    wrote %d Bytes\n", (int)(offset), len);
    *eof = 1;
    return len;
    }

    /*
    * Fill the buffer and get its length
    */
    len = sprintf(buffer,
    "For the %d%s time, go away!\n", count,
    (count % 100 > 10 && count % 100 < 14) ? "th" :
    (count % 10 == 1) ? "st" :
    (count % 10 == 2) ? "nd" :
    (count % 10 == 3) ? "rd" : "th" );
    count++;

    /*
    * Return the length
    */
    printk(KERN_INFO
    "leaving /proc/test : procfile_read, wrote %d Bytes\n", len);
    return len;
    }

    int init_module()
    {
    int rv = 0;
    Our_Proc_File = create_proc_entry("test", 0644, NULL);
    Our_Proc_File->read_proc = procfile_read;
    Our_Proc_File->owner = THIS_MODULE;
    Our_Proc_File->mode = S_IFREG | S_IRUGO;
    Our_Proc_File->uid = 0;
    Our_Proc_File->gid = 0;
    Our_Proc_File->size = 37;

    printk(KERN_INFO "Trying to create /proc/test:\n" );

    if (Our_Proc_File == NULL) {
    rv = -ENOMEM;
    remove_proc_entry("test", &proc_root);
    printk(KERN_INFO "Error: Could not initialize /proc/test\n" );
    } else {
    printk(KERN_INFO "Success!\n" );
    }

    return rv;
    }

    void cleanup_module()
    {
    remove_proc_entry("test", &proc_root);
    printk(KERN_INFO "/proc/test removed\n" );
    }
    Notes
    [1] ÕâÊÇÔÚ2.0°æ±¾ÖеÄ×ö·¨£¬ ÔÚ°æ±¾2.2ÖУ¬µ±ÎÒÃÇ°ÑinodeÉèΪ0ʱ£¬¾ÍÒѾ­ÕâÑù×Ô¶¯´¦ÀíÁË¡£

  15. febspeolal ÓÚ 2006-11-09 01:09:11·¢±í:

    Chapter 4. Character Device Files
    ×Ö·ûÉ豸Îļþ
    ¹ØÓÚfile_operations½á¹¹Ìå
    ½á¹¹Ìåfile_operationsÔÚÍ·Îļþ linux/fs.hÖж¨Ò壬ÓÃÀ´´æ´¢Çý¶¯ÄÚºËÄ£¿éÌṩµÄ¶Ô É豸½øÐи÷ÖÖ²Ù×÷µÄº¯ÊýµÄÖ¸Õë¡£¸Ã½á¹¹ÌåµÄÿ¸öÓò¶¼¶ÔÓ¦×ÅÇý¶¯ÄÚºËÄ£¿éÓÃÀ´´¦Àíij¸ö±»ÇëÇóµÄ ÊÂÎñµÄº¯ÊýµÄµØÖ·¡£

    ¾Ù¸öÀý×Ó£¬Ã¿¸ö×Ö·ûÉ豸ÐèÒª¶¨ÒåÒ»¸öÓÃÀ´¶ÁÈ¡É豸Êý¾ÝµÄº¯Êý¡£½á¹¹Ìå file_operationsÖд洢×ÅÄÚºËÄ£¿éÖÐÖ´ÐÐÕâÏî²Ù×÷µÄº¯ÊýµÄµØÖ·¡£Ò»ÏÂÊǸýṹÌå ÔÚÄÚºË2.6.5Öп´ÆðÀ´µÄÑù×Ó£º

    struct file_operations {
    struct module *owner;
    loff_t(*llseek) (struct file *, loff_t, int);
    ssize_t(*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t(*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
    ssize_t(*write) (struct file *, const char __user *, size_t, loff_t *);
    ssize_t(*aio_write) (struct kiocb *, const char __user *, size_t,
    loff_t);
    int (*readdir) (struct file *, void *, filldir_t);
    unsigned int (*poll) (struct file *, struct poll_table_struct *);
    int (*ioctl) (struct inode *, struct file *, unsigned int,
    unsigned long);
    int (*mmap) (struct file *, struct vm_area_struct *);
    int (*open) (struct inode *, struct file *);
    int (*flush) (struct file *);
    int (*release) (struct inode *, struct file *);
    int (*fsync) (struct file *, struct dentry *, int datasync);
    int (*aio_fsync) (struct kiocb *, int datasync);
    int (*fasync) (int, struct file *, int);
    int (*lock) (struct file *, int, struct file_lock *);
    ssize_t(*readv) (struct file *, const struct iovec *, unsigned long,
    loff_t *);
    ssize_t(*writev) (struct file *, const struct iovec *, unsigned long,
    loff_t *);
    ssize_t(*sendfile) (struct file *, loff_t *, size_t, read_actor_t,
    void __user *);
    ssize_t(*sendpage) (struct file *, struct page *, int, size_t,
    loff_t *, int);
    unsigned long (*get_unmapped_area) (struct file *, unsigned long,
    unsigned long, unsigned long,
    unsigned long);
    };

    Çý¶¯ÄÚºËÄ£¿éÊDz»ÐèҪʵÏÖÿ¸öº¯ÊýµÄ¡£ÏñÊÓƵ¿¨µÄÇý¶¯¾Í²»ÐèÒª´ÓĿ¼µÄ½á¹¹ ÖжÁÈ¡Êý¾Ý¡£ÄÇô£¬Ïà¶ÔÓ¦µÄfile_operationsÖصÄÏî¾ÍΪ NULL¡£

    gcc»¹ÓÐÒ»¸ö·½±ãʹÓÃÕâÖֽṹÌåµÄÀ©Õ¹¡£Äã»áÔÚ½ÏÏÖ´úµÄÇý¶¯ÄÚºËÄ£¿éÖмûµ½¡£ еÄʹÓÃÕâÖֽṹÌåµÄ·½Ê½ÈçÏ£º

    struct file_operations fops = {
    read: device_read,
    write: device_write,
    open: device_open,
    release: device_release
    };

    ͬÑùÒ²ÓÐC99Óï·¨µÄʹÓøýṹÌåµÄ·½·¨£¬²¢ÇÒËü±ÈGNUÀ©Õ¹¸üÊÜÍƼö¡£ÎÒʹÓõİ汾Ϊ 2.95ΪÁË·½±ãÄÇЩÏëÒÆÖ²ÄãµÄ´úÂëµÄÈË£¬Äã×îºÃʹÓÃÕâÖÖÓï·¨¡£Ëü½«Ìá¸ß´úÂëµÄ¼æÈÝÐÔ£º

    struct file_operations fops = {
    .read = device_read,
    .write = device_write,
    .open = device_open,
    .release = device_release
    };

    ÕâÖÖÓï·¨ºÜÇåÎú£¬ÄãÒ²±ØÐëÇå³þµÄÒâʶµ½Ã»ÓÐÏÔʾÉùÃ÷µÄ½á¹¹Ìå³ÉÔ±¶¼±»gcc³õʼ»¯ÎªNULL¡£

    Ö¸Ïò½á¹¹Ìåstruct file_operationsµÄÖ¸Õëͨ³£ÃüÃûΪfops¡£

    ¹ØÓÚfile½á¹¹Ìå
    ÿһ¸öÉ豸Îļþ¶¼´ú±í×ÅÄÚºËÖеÄÒ»¸öfile½á¹¹Ìå¡£¸Ã½á¹¹ÌåÔÚÍ·Îļþlinux/fs.h¶¨Òå¡£×¢Ò⣬file½á¹¹ÌåÊÇÄں˿ռäµÄ½á¹¹Ì壬 ÕâÒâζ×ÅËü²»»áÔÚÓû§³ÌÐòµÄ´úÂëÖгöÏÖ¡£Ëü¾ø¶Ô²»ÊÇÔÚglibcÖж¨ÒåµÄFILE¡£ FILE×Ô¼ºÒ²´Ó²»ÔÚÄں˿ռäµÄº¯ÊýÖгöÏÖ¡£ËüµÄÃû×ÖȷʵͦÈÃÈËÃÔ»óµÄ¡£ Ëü´ú±í×ÅÒ»¸ö³éÏóµÄ´ò¿ªµÄÎļþ£¬µ«²»ÊÇÄÇÖÖÔÚ´ÅÅÌÉÏÓýṹÌå inode±íʾµÄÎļþ¡£

    Ö¸Ïò½á¹¹Ìåstruct fileµÄÖ¸Õëͨ³£ÃüÃûΪfilp¡£ ÄãͬÑù¿ÉÒÔ¿´µ½struct file fileµÄ±í´ï·½Ê½£¬µ«²»Òª±»ËüÓÕ»ó¡£

    È¥¿´¿´½á¹¹ÌåfileµÄ¶¨Òå¡£´ó²¿·ÖµÄº¯ÊýÈë¿Ú£¬Ïñ½á¹¹Ìå struct dentryûÓб»É豸Çý¶¯Ä£¿éʹÓã¬Äã´ó¿ÉºöÂÔËüÃÇ¡£ÕâÊÇÒòΪÉ豸Çý¶¯Ä£¿é²¢²»×Ô¼ºÖ±½ÓÌî³ä½á¹¹Ìå file£ºËüÃÇÖ»ÊÇʹÓÃÔڱ𴦽¨Á¢µÄ½á¹¹ÌåfileÖеÄÊý¾Ý¡£

    ×¢²áÒ»¸öÉ豸
    ÈçͬÏÈÇ°ÌÖÂ۵ģ¬×Ö·ûÉ豸ͨ³£Í¨¹ýÔÚ·¾¶/dev[1]É豸ÎÄ ¼þ·ÃÎÊ¡£Ö÷É豸ºÅ¸æËßÄãÄÄЩÇý¶¯Ä£¿éÊÇÓÃÀ´²Ù×ÝÄÄЩӲ¼þÉ豸µÄ¡£´ÓÉ豸ºÅÊÇÇý¶¯Ä£ ¿é×Ô¼ºÊ¹ÓÃÀ´Çø±ðËü²Ù×ݵIJ»Í¬É豸£¬µ±´ËÇý¶¯Ä£¿é²Ù×ݲ»Ö»Ò»¸öÉ豸ʱ¡£

    ½«ÄÚºËÇý¶¯Ä£¿é¼ÓÔØÈëÄÚºËÒâζ×ÅÒªÏòÄÚºË×¢²á×Ô¼º¡£Õâ¸ö¹¤×÷ÊǺÍÇý¶¯Ä£¿é»ñ µÃÖ÷É豸ºÅʱ³õʼ»¯Ò»Í¬½øÐеġ£Äã¿ÉÒÔʹÓÃÍ·Îļþ linux/fs.hÖеĺ¯Êýregister_chrdevÀ´Êµ ÏÖ¡£

    int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);

    ÆäÖÐunsigned int majorÊÇÄãÉêÇëµÄÖ÷É豸ºÅ£¬ const char *nameÊǽ«ÒªÔÚÎļþ/proc/devices struct file_operations *fopsÊÇÖ¸ÏòÄãµÄÇý¶¯Ä£¿éµÄ file_operations±íµÄÖ¸Õë¡£¸ºµÄ·µ»ØÖµÒâζ×Å×¢²áʧ°Ü¡£ ×¢Òâ×¢²á²¢²»ÐèÒªÌṩ´ÓÉ豸ºÅ¡£Äں˱¾Éí²¢²»ÔÚÒâ´ÓÉ豸ºÅ¡£

    ÏÖÔÚµÄÎÊÌâÊÇÄãÈçºÎÉêÇëµ½Ò»¸öûÓб»Ê¹ÓõÄÖ÷É豸ºÅ£¿×î¼òµ¥µÄ·½·¨ÊDz鿴Îļþ Documentation/devices.txt´ÓÖÐÌôÑ¡Ò»¸öûÓб»Ê¹Óõġ£Õâ²»ÊÇ Ò»ÀÍÓÀÒݵķ½·¨ÒòΪÄãÎÞ·¨µÃÖª¸ÃÖ÷É豸ºÅÔÚ½«À´»á±»Õ¼Óá£×îÖյķ½·¨ÊÇÈÃÄÚºËΪÄ㶯 ̬·ÖÅäÒ»¸ö¡£

    Èç¹ûÄãÏòº¯Êýregister_chrdev´«µÝΪ0µÄÖ÷É豸ºÅ£¬ÄÇô ·µ»ØµÄ¾ÍÊǶ¯Ì¬·ÖÅäµÄÖ÷É豸ºÅ¡£¸±×÷ÓþÍÊǼÈÈ»ÄãÎÞ·¨µÃÖªÖ÷É豸ºÅ£¬Äã¾ÍÎÞ·¨Ô¤ÏȽ¨ Á¢Ò»¸öÉ豸Îļþ¡£ ÓжàÖÖ½â¾ö·½·¨¡£µÚÒ»ÖÖ·½·¨ÊÇÐÂ×¢²áµÄÇý¶¯Ä£¿é»áÊä³ö×Ô¼ºÐ·ÖÅä µ½µÄÖ÷É豸ºÅ£¬ËùÒÔÎÒÃÇ¿ÉÒÔÊÖ¹¤½¨Á¢ÐèÒªµÄÉ豸Îļþ¡£µÚ¶þÖÖÊÇÀûÓÃÎļþ /proc/devicesÐÂ×¢²áµÄÇý¶¯Ä£¿éµÄÈë¿Ú£¬ÒªÃ´ÊÖ¹¤½¨Á¢É豸Îļþ£¬ Ҫô±àÒ»¸ö½Å±¾È¥×Ô¶¯¶ÁÈ¡¸ÃÎļþ²¢ÇÒÉú³ÉÉ豸Îļþ¡£µÚÈýÖÖÊÇÔÚÎÒÃǵÄÄ£¿éÖУ¬µ±×¢²á ³É¹¦Ê±£¬Ê¹ÓÃmknodͳµ÷Óý¨Á¢É豸Îļþ²¢ÇÒµ÷Óà rm ɾ³ý¸ÃÉ豸 ÎļþÔÚÇý¶¯Ä£¿éµ÷Óú¯Êýcleanup_moduleÇ°¡£

    ×¢ÏúÒ»¸öÉ豸
    ¼´Ê¹Ê±rootÒ²²»ÄÜÔÊÐíËæÒâжÔØÄÚºËÄ£¿é¡£µ±Ò»¸ö½ø³ÌÒѾ­´ò¿ªÒ»¸öÉ豸ÎļþʱÎÒ ÃÇжÔØÁ˸ÃÉ豸ÎļþʹÓõÄÄÚºËÄ£¿é£¬ÎÒÃÇ´ËʱÔÙ¶Ô¸ÃÎļþµÄ·ÃÎʽ«»áµ¼Ö¶ÔÒÑжÔصÄÄÚ ºËÄ£¿é´úÂëÄÚ´æÇøµÄ·ÃÎÊ¡£ÐÒÔ˵Ļ°ÎÒÃÇ×î¶à»ñµÃÒ»¸öÌÖÑáµÄ´íÎ󾯸档Èç¹û´ËʱÒѾ­ÔÚ ¸ÃÄÚ´æÇø¼ÓÔØÁËÁíÒ»¸öÄ£¿é£¬µ¹Ã¹µÄÄ㽫»áÔÚÄÚºËÖÐÌøתִÐÐÒâÁÏÍâµÄ´úÂë¡£½á¹ûÊÇÎÞ·¨ Ô¤Áϵģ¬¶øÇÒ¶à°ëÊDz»ÄÇôÁîÈËÓä¿ìµÄ¡£

    ƽ³££¬µ±Äã²»ÔÊÐíijÏî²Ù×÷ʱ£¬Äã»áµÃµ½¸Ã²Ù×÷·µ»ØµÄ´íÎóÖµ£¨Ò»°ãΪһ¸ºµÄÖµ£©¡£ µ«¶ÔÓÚÎÞ·µ»ØÖµµÄº¯Êýcleanup_moduleÕâÊDz»¿ÉÄܵġ£È»¶ø£¬È´ÓÐ Ò»¸ö¼ÆÊýÆ÷¸ú×Ù×ÅÓжàÉÙ½ø³ÌÕýÔÚʹÓøÃÄ£¿é¡£Äã¿ÉÒÔͨ¹ý²é¿´Îļþ /proc/modulesµÄµÚÈýÁÐÀ´»ñÈ¡ÕâЩÐÅÏ¢¡£Èç¹û¸ÃÖµ·ÇÁ㣬ÔòжÔØ ¾Í»áʧ°Ü¡£Äã²»ÐèÒªÔÚÄãÄ£¿éÖеĺ¯Êýcleanup_moduleÖмì²é¸Ã ¼ÆÊýÆ÷£¬ÒòΪ¸ÃÏî¼ì²éÓÉÍ·Îļþlinux/module.cÖж¨ÒåµÄϵͳµ÷Óà sys_delete_moduleÍê³É¡£ÄãÒ²²»Ó¦¸ÃÖ±½Ó¶Ô¸Ã¼ÆÊýÆ÷½øÐвÙ×÷¡£ ÄãÓ¦¸ÃʹÓÃÔÚÎļþlinux/modules.h¶¨ÒåµÄºê À´Ôö¼Ó£¬¼õСºÍ¶ÁÈ¡¸Ã¼ÆÊýÆ÷£º


    try_module_get(THIS_MODULE): Increment the use count.

    try_module_put(THIS_MODULE): Decrement the use count.

    ±£³Ö¸Ã¼ÆÊýÆ÷ʱ¿Ì¾«È·ÊǷdz£ÖØÒªµÄ£»Èç¹ûÄ㶪ʧÁËÕýÈ·µÄ¼ÆÊý£¬Ä㽫ÎÞ·¨Ð¶ÔØÄ£¿é£¬ ÄǾÍÖ»ÓÐÖØÆôÁË¡£²»¹ýÕâÖÖÇé¿öÔÚ½ñºó±àдÄÚºËÄ£¿éʱҲÊÇÎÞ·¨±ÜÃâµÄ¡£

    chardev.c
    ÏÂÃæµÄ´úÂëʾ·¶ÁËÒ»¸ö½Ð×öchardevµÄ×Ö·ûÉ豸¡£Äã¿ÉÒÔÓà catÊä³ö¸ÃÉ豸ÎļþµÄÄÚÈÝ£¨»òÓñðµÄ³ÌÐò´ò¿ªËü£©Ê±£¬Çý¶¯Ä£¿é »á½«¸ÃÉ豸Îļþ±»¶ÁÈ¡µÄ´ÎÊýÏÔʾ¡£Ä¿Ç°¶ÔÉ豸ÎļþµÄд²Ù×÷»¹²»±»Ö§³Ö£¨Ïñecho "hi" > /dev/hello£©£¬µ«»á²¶×½ÕâЩ²Ù×÷²¢ÇÒ¸æËßÓû§¸Ã²Ù×÷²»±»Ö§³Ö¡£²»Òªµ£ÐÄÎÒ ÃǶԶÁÈ뻺³åÇøµÄÊý¾Ý×öÁËʲô£»ÎÒÃÇʲô¶¼Ã»×ö¡£ÎÒÃÇÖ»ÊǶÁÈëÊý¾Ý²¢Êä³öÎÒÃÇÒѾ­½Ó ÊÕµ½µÄÊý¾ÝµÄÐÅÏ¢¡£

    Example 4-1. chardev.c

    /*
    * chardev.c: Creates a read-only char device that says how many times
    * you've read from the dev file
    */

    #include
    #include
    #include
    #include /* for put_user */

    /*
    * Prototypes - this would normally go in a .h file
    */
    int init_module(void);
    void cleanup_module(void);
    static int device_open(struct inode *, struct file *);
    static int device_release(struct inode *, struct file *);
    static ssize_t device_read(struct file *, char *, size_t, loff_t *);
    static ssize_t device_write(struct file *, const char *, size_t, loff_t *);

    #define SUCCESS 0
    #define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices */
    #define BUF_LEN 80 /* Max length of the message from the device */

    /*
    * Global variables are declared as static, so are global within the file.
    */

    static int Major; /* Major number assigned to our device driver */
    static int Device_Open = 0; /* Is device open?
    * Used to prevent multiple access to device */
    static char msg[BUF_LEN]; /* The msg the device will give when asked */
    static char *msg_Ptr;

    static struct file_operations fops = {
    .read = device_read,
    .write = device_write,
    .open = device_open,
    .release = device_release
    };

    /*
    * Functions
    */

    int init_module(void)
    {
    Major = register_chrdev(0, DEVICE_NAME, &fops);

    if (Major < 0) {
    printk("Registering the character device failed with %d\n",
    Major);
    return Major;
    }

    printk("<1>I was assigned major number %d. To talk to\n", Major);
    printk("<1>the driver, create a dev file with\n");
    printk("'mknod /dev/hello c %d 0'.\n", Major);
    printk("<1>Try various minor numbers. Try to cat and echo to\n");
    printk("the device file.\n");
    printk("<1>Remove the device file and module when done.\n");

    return 0;
    }

    void cleanup_module(void)
    {
    /*
    * Unregister the device
    */
    int ret = unregister_chrdev(Major, DEVICE_NAME);
    if (ret < 0)
    printk("Error in unregister_chrdev: %d\n", ret);
    }

    /*
    * Methods
    */

    /*
    * Called when a process tries to open the device file, like
    * "cat /dev/mycharfile"
    */
    static int device_open(struct inode *inode, struct file *file)
    {
    static int counter = 0;
    if (Device_Open)
    return -EBUSY;
    Device_Open++;
    sprintf(msg, "I already told you %d times Hello world!\n", counter++);
    msg_Ptr = msg;
    try_module_get(THIS_MODULE);

    return SUCCESS;
    }

    /*
    * Called when a process closes the device file.
    */
    static int device_release(struct inode *inode, struct file *file)
    {
    Device_Open--; /* We're now ready for our next caller */

    /*
    * Decrement the usage count, or else once you opened the file, you'll
    * never get get rid of the module.
    */
    module_put(THIS_MODULE);

    return 0;
    }

    /*
    * Called when a process, which already opened the dev file, attempts to
    * read from it.
    */
    static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
    char *buffer, /* buffer to fill with data */
    size_t length, /* length of the buffer */
    loff_t * offset)
    {
    /*
    * Number of bytes actually written to the buffer
    */
    int bytes_read = 0;

    /*
    * If we're at the end of the message,
    * return 0 signifying end of file
    */
    if (*msg_Ptr == 0)
    return 0;

    /*
    * Actually put the data into the buffer
    */
    while (length && *msg_Ptr) {

    /*
    * The buffer is in the user data segment, not the kernel
    * segment so "*" assignment won't work. We have to use
    * put_user which copies data from the kernel data segment to
    * the user data segment.
    */
    put_user(*(msg_Ptr++), buffer++);

    length--;
    bytes_read++;
    }

    /*
    * Most read functions return the number of bytes put into the buffer
    */
    return bytes_read;
    }

    /*
    * Called when a process writes to dev file: echo "hi" > /dev/hello
    */
    static ssize_t
    device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
    {
    printk("<1>Sorry, this operation isn't supported.\n");
    return -EINVAL;
    }
    Ϊ¶à¸ö°æ±¾µÄÄں˱àдÄÚºËÄ£¿é
    ϵͳµ÷Óã¬Ò²¾ÍÊÇÄÚºËÌṩ¸ø½ø³ÌµÄ½Ó¿Ú£¬»ù±¾ÉÏÊDZ£³Ö²»±äµÄ¡£Ò²Ðí»áÌíÈëÐÂµÄ ÏµÍ³µ÷Ó㬵«ÄÇЩÒÑÓеIJ»»á±»¸Ä¶¯¡£Õâ¶ÔÓÚÏòϼæÈÝÊǷdz£ÖØÒªµÄ¡£ÔÚ¶àÊýÇé¿öÏ£¬Éè ±¸ÎļþÊDZ£³Ö²»±äµÄ¡£µ«Äں˵ÄÄÚ²¿ÔÚ²»Í¬°æ±¾Ö®¼ä»¹ÊÇ»áÓÐÇø±ðµÄ¡£

    LinuxÄں˷ÖΪÎȶ¨°æ±¾£¨°æ±¾ºÅÖмäΪżÊý£©ºÍÊÔÑé°æ±¾£¨°æ±¾ºÅÖмäΪÆæÊý£©¡£ ÊÔÑé°æ±¾ÖпÉÒÔÊÔÑé¸÷ÖÖ¸÷ÑùµÄжø¿áµÄÖ÷Ò⣬ÓÐЩ»á±»Ö¤ÊµÊÇÒ»¸ö´íÎó£¬ÓÐЩÔÚÏÂÒ»°æ ÖлᱻÍêÉÆ¡£×ÜÖ®£¬Äã²»ÄÜÒÀÀµÕâЩ°æ±¾ÖеĽӿڣ¨ÕâÒ²ÊÇÎÒ²»ÔÚ±¾ÎĵµÖÐÖ§³ÖËüÃǵÄÔ­Òò£¬ ËüÃǸüеÄÌ«¿ìÁË)¡£ÔÚÎȶ¨°æ±¾ÖУ¬ÎÒÃÇ¿ÉÒÔÆÚÍû½Ó¿Ú±£³ÖÒ»Ö£¬³ýÁËÄÇЩÐ޸ĴúÂëÖдíÎóµÄ°æ±¾¡£

    Èç¹ûÄãÒªÖ§³Ö¶à°æ±¾µÄÄںˣ¬ÄãÐèÒª±àдΪ²»Í¬Äں˱àÒëµÄ´úÂëÊ÷¡£¿ÉÒÔͨ¹ý±È½Ïºê LINUX_VERSION_CODEºÍºêKERNEL_VERSIONÔÚ°æ±¾ºÅΪa.b.c µÄÄÚºËÖУ¬¸ÃºêµÄÖµÓ¦¸ÃΪ 2^16¡Áa+2^8¡Áb+c

    ÔÚÉÏÒ»¸ö°æ±¾ÖиÃÎĵµ»¹±£ÁôÁËÏêϸµÄÈçºÎÏòºó¼æÈÝÀÏÄں˵ĽéÉÜ£¬ÏÖÔÚÎÒÃǾö¶¨´òÆÆÕâ¸ö´«Í³¡£ ¶ÔΪÀÏÄں˱àдÇý¶¯¸ÐÐËȤµÄ¶ÁÕßÓ¦¸Ã²Î¿¼¶ÔÓ¦°æ±¾µÄLKMPG£¬Ò²¾ÍÊÇ˵£¬2.4.x°æ±¾µÄLKMPG¶ÔÓ¦ 2.4.xµÄÄںˣ¬2.6.x°æ±¾µÄLKMPG¶ÔÓ¦2.6.xµÄÄںˡ£

    Notes
    [1] ÕâÖ»ÊÇÏ°¹ßÉϵġ£½«É豸Îļþ·Å ÔÚÄãµÄÓû§Ä¿Â¼ÏÂÊÇûÓÐÎÊÌâµÄ¡£µ«Êǵ±ÕæÕýÌṩ³ÉÊìµÄÇý¶¯Ä£¿éʱ£¬Çë±£Ö¤½«É豸ÎÄ ¼þ·ÅÔÚ/devÏ¡£

  16. febspeolal ÓÚ 2006-11-09 01:08:47·¢±í:

    Chapter 3. Preliminaries
    ÄÚºËÄ£¿éºÍÓû§³ÌÐòµÄ±È½Ï
    ÄÚºËÄ£¿éÊÇÈçºÎ¿ªÊ¼ºÍ½áÊøµÄ
    Óû§³ÌÐòͨ³£´Óº¯Êýmain()¿ªÊ¼£¬Ö´ÐÐһϵÁеÄÖ¸Áî²¢ÇÒ µ±Ö¸ÁîÖ´ÐÐÍê³Éºó½áÊø³ÌÐò¡£ÄÚºËÄ£¿éÓÐÒ»µã²»Í¬¡£ÄÚºËÄ£¿éҪô´Óº¯Êýinit_module »òÊÇÄãÓúêmodule_initÖ¸¶¨µÄº¯Êýµ÷ÓÿªÊ¼¡£Õâ¾ÍÊÇÄÚºËÄ£¿é µÄÈë¿Úº¯Êý¡£Ëü¸æËßÄÚºËÄ£¿éÌṩÄÇЩ¹¦ÄÜÀ©Õ¹²¢ÇÒÈÃÄÚºË×¼±¸ºÃÔÚÐèҪʱµ÷ÓÃËü¡£ µ±ËüÍê³ÉÕâЩºó£¬¸Ãº¯Êý¾ÍÖ´ÐнáÊøÁË¡£Ä£¿éÔÚ±»Äں˵÷ÓÃǰҲʲô¶¼²»×ö¡£

    ËùÓеÄÄ£¿é»òÊǵ÷ÓÃcleanup_module»òÊÇÄãÓúê module_exitÖ¸¶¨µÄº¯Êý¡£ÕâÊÇÄ£¿éµÄÍ˳öº¯Êý¡£Ëü³·ÏûÈë¿Úº¯ÊýËù×öµÄÒ»ÇС£ ÀýÈç×¢ÏúÈë¿Úº¯ÊýËù×¢²áµÄ¹¦ÄÜ¡£

    ËùÓеÄÄ£¿é¶¼±ØÐëÓÐÈë¿Úº¯ÊýºÍÍ˳öº¯Êý¡£¼ÈÈ»ÎÒÃÇÓв»Ö»Ò»ÖÖ·½·¨È¥¶¨ÒåÕâÁ½¸ö º¯Êý£¬ÎÒ½«Å¬Á¦Ê¹Óá°Èë¿Úº¯Êý¡±ºÍ¡°Í˳öº¯Êý¡±À´ÃèÊö ËüÃÇ¡£µ«Êǵ±ÎÒÖ»ÓÃinit_module ºÍcleanup_moduleʱ£¬ÎÒÏ£ÍûÄãÃ÷°×ÎÒÖ¸µÄÊÇʲô¡£

    Ä£¿é¿Éµ÷Óõĺ¯Êý
    ³ÌÐòÔ±²¢²»×ÜÊÇ×Ô¼ºÐ´ËùÓÐÓõ½µÄº¯Êý¡£Ò»¸ö³£¼ûµÄ»ù±¾µÄÀý×Ó¾ÍÊÇ printf()ÄãʹÓÃÕâЩC±ê×¼¿â£¬libcÌṩµÄ¿âº¯Êý¡£ ÕâЩº¯Êý(Ïñprintf()) ʵ¼ÊÉÏÔÚÁ¬½Ó֮ǰ²¢²»½øÈëÄãµÄ³ÌÐò¡£ ÔÚÁ¬½ÓʱÕâЩº¯Êýµ÷ÓòŻáÖ¸Ïò Äãµ÷ÓõĿ⣬´Ó¶øʹÄãµÄ´úÂë×îÖÕ¿ÉÒÔÖ´ÐС£

    ÄÚºËÄ£¿éÓÐËù²»Í¬¡£ÔÚhello worldÄ£¿éÖÐÄãÒ²ÐíÒѾ­×¢Òâµ½ÁËÎÒÃÇʹÓõĺ¯Êý printk() ȴûÓаüº¬±ê×¼I/O¿â¡£ÕâÊÇÒòΪģ¿éÊÇÔÚinsmod¼Ó ÔØʱ²ÅÁ¬½ÓµÄÄ¿±êÎļþ¡£ÄÇЩҪÓõ½µÄº¯ÊýµÄ·ûºÅÁ´½ÓÊÇÄÚºË×Ô¼ºÌṩµÄ¡£ Ò²¾ÍÊÇ˵£¬ Äã¿ÉÒÔÔÚÄÚºËÄ£¿éÖÐʹÓõĺ¯ÊýÖ»ÄÜÀ´×ÔÄں˱¾Éí¡£Èç¹ûÄã¶ÔÄÚºËÌṩÁËÄÄЩº¯Êý·ûºÅ Á´½Ó¸ÐÐËȤ£¬¿´Ò»¿´Îļþ/proc/kallsyms¡£

    ÐèҪעÒâµÄÒ»µãÊǿ⺯ÊýºÍϵͳµ÷ÓõÄÇø±ð¡£¿âº¯ÊýÊǸ߲ãµÄ£¬ÍêÈ«ÔËÐÐÔÚÓû§¿Õ¼ä£¬ Ϊ³ÌÐòÔ±Ìṩµ÷ÓÃÕæÕýµÄÔÚÄ»ºó Íê³Éʵ¼ÊÊÂÎñµÄϵͳµ÷Óõĸü·½±ãµÄ½Ó¿Ú¡£ÏµÍ³µ÷ÓÃÔÚÄÚºË Ì¬ÔËÐв¢ÇÒÓÉÄÚºË×Ô¼ºÌṩ¡£±ê×¼C¿âº¯Êýprintf()¿ÉÒÔ±»¿´×öÊÇÒ» ¸öͨÓõÄÊä³öÓï¾ä£¬µ«Ëüʵ¼Ê×öµÄÊǽ«Êý¾Ýת»¯Îª·ûºÏ¸ñʽµÄ×Ö·û´®²¢ÇÒµ÷ÓÃϵͳµ÷Óà write()Êä³öÕâЩ×Ö·û´®¡£

    ÊÇ·ñÏë¿´Ò»¿´printf()¾¿¾¹Ê¹ÓÃÁËÄÄЩϵͳµ÷ÓÃ? ÕâºÜÈÝÒ×£¬±àÒëÏÂÃæµÄ´úÂë¡£

    #include
    int main(void)
    { printf("hello" ); return 0; }

    ʹÓÃÃüÁîgcc -Wall -o hello hello.c±àÒë¡£ÓÃÃüÁî strace helloÐиÿÉÖ´ÐÐÎļþ¡£ÊÇ·ñºÜ¾ªÑÈ£¿ ÿһÐж¼ºÍÒ»¸öϵͳµ÷ÓÃÏà¶ÔÓ¦¡£ strace[1] ÊÇÒ»¸ö·Ç³£ÓÐÓõijÌÐò£¬Ëü¿ÉÒÔ¸æËßÄã³ÌÐòʹÓÃÁËÄÄЩϵͳµ÷ÓúÍÕâЩϵͳµ÷ÓõIJÎÊý£¬·µ»ØÖµ¡£ ÕâÊÇÒ»¸ö¼«ÓмÛÖµµÄ²é¿´³ÌÐòÔÚ¸ÉʲôµÄ¹¤¾ß¡£ÔÚÊä³öµÄĩ⣬ÄãÓ¦¸Ã¿´µ½ÕâÑùÀàËƵÄÒ»ÐÐ write(1, "hello", 5hello)¡£Õâ¾ÍÊÇÎÒÃÇÒªÕҵġ£²ØÔÚÃæ¾ßprintf() µÄÕæʵÃæÄ¿¡£¼ÈÈ»¾ø´ó¶àÊýÈËʹÓÿ⺯ÊýÀ´¶ÔÎļþI/O½øÐвÙ×÷(Ïñ fopen, fputs, fclose)¡£ Äã¿ÉÒԲ鿴man˵Ã÷µÄµÚ¶þ²¿·ÖʹÓÃÃüÁîman 2 write. ¡£man˵Ã÷µÄµÚ¶þ²¿·Ö רÃŽéÉÜϵͳµ÷ÓÃ(Ïñkill()ºÍread())¡£ man˵Ã÷µÄµÚÈý²¿·ÖÔòרÃŽéÉÜÄã¿ÉÄܸüÊìϤµÄ¿âº¯Êý£¬ (Ïñcosh()ºÍrandom())¡£

    ÄãÉõÖÁ¿ÉÒÔ±àд´úÂëÈ¥¸²¸Çϵͳµ÷Óã¬ÕýÈçÎÒÃDz»¾ÃÒª×öµÄ¡£º§¿Í³£ÕâÑù×öÀ´ÎªÏµÍ³°²×°ºóÃÅ»òľÂí¡£ µ«Äã¿ÉÒÔÓÃËüÀ´Íê³ÉһЩ¸üÓÐÒæµÄÊ£¬ÏñÈÃÄÚºËÔÚÿ´ÎijÈËɾ³ýÎļþʱÊä³ö ¡° Tee hee, that tickles!¡± µÄÐÅÏ¢¡£

    Óû§¿Õ¼äºÍÄں˿ռä
    ÄÚºËȫȨ¸ºÔð¶ÔÓ²¼þ×ÊÔ´µÄ·ÃÎÊ£¬²»¹Ü±»·ÃÎʵÄÊÇÏÔʾ¿¨£¬Ó²ÅÌ£¬»¹ÊÇÄÚ´æ¡£ Óû§³ÌÐò³£ÎªÕâЩ×ÊÔ´¾ºÕù¡£¾ÍÈçͬÎÒÔÚ±£´æÕâ ·ÝÎĵµÍ¬Ê±±¾µØÊý¾Ý¿âÕýÔÚ¸üС£ Îҵı༭Æ÷vim½ø³ÌºÍÊý¾Ý¿â¸üнø³ÌͬʱҪÇó·ÃÎÊÓ²ÅÌ¡£Äں˱ØÐëʹÕâЩÇëÇóÓÐÌõ²»ÎɵĽøÐУ¬ ¶ø²»ÊÇËæÓû§µÄÒâÔ¸Ìṩ¼ÆËã»ú×ÊÔ´¡£ Ϊ·½±ãʵÏÖÕâÖÖ»úÖÆ£¬ CPU ¿ÉÒÔÔÚ²»Í¬µÄ״̬ÔËÐС£²»Í¬µÄ״̬¸³Ó費ͬµÄÄã¶Ôϵͳ²Ù×÷µÄ×ÔÓÉ¡£Intel 80836 ¼Ü¹¹ÓÐËÄÖÖ״̬¡£ UnixֻʹÓÃÁËÆäÖÐ µÄÁ½ÖÖ£¬×î¸ß¼¶µÄ״̬(²Ù×÷״̬0,¼´¡°³¬¼¶×´Ì¬¡±£¬¿ÉÒÔÖ´ÐÐÈκβÙ×÷)ºÍ×îµÍ¼¶µÄ״̬ (¼´¡°Óû§×´Ì¬¡±)¡£

    »ØÒäÒÔÏÂÎÒÃǶԿ⺯ÊýºÍϵͳµ÷ÓõÄÌÖÂÛ£¬Ò»°ã¿âº¯ÊýÔÚÓû§Ì¬Ö´ÐС£ ¿âº¯Êýµ÷ÓÃÒ»¸ö»ò¼¸¸öϵͳµ÷Ó㬶øÕâЩϵͳµ÷ÓÃΪ¿âº¯ÊýÍê³É¹¤×÷£¬µ«ÊÇÔÚ³¬¼¶×´Ì¬¡£ Ò»µ©ÏµÍ³µ÷ÓÃÍê³É¹¤×÷ºóϵͳµ÷Óþͷµ»Øͬʱ³ÌÐòÒ²·µ»ØÓû§Ì¬¡£

    ÃüÃû¿Õ¼ä
    Èç¹ûÄãÖ»ÊÇдһЩ¶ÌСµÄC³ÌÐò£¬Äã¿ÉΪÄãµÄ±äÁ¿ÆðÒ»¸ö·½±ãµÄºÍÒ×ÓÚÀí½âµÄ±äÁ¿Ãû¡£ µ«ÊÇ£¬Èç¹ûÄãдµÄ´úÂëÖ»ÊÇ Ðí¶àÆäËüÈËдµÄ´úÂëµÄÒ»²¿·Ö£¬ÄãµÄÈ«¾ÖһЩ¾Í»áÓëÆäÖеÄÈ«¾Ö±äÁ¿·¢Éú³åÍ»¡£ ÁíÒ»¸öÇé¿öÊÇÒ»¸ö³ÌÐòÖÐÓÐÌ«¶àµÄ ÄÑÒÔÀí½âµÄ±äÁ¿Ãû£¬ÕâÓֻᵼÖ±äÁ¿ÃüÃû¿Õ¼äÎÛȾ ÔÚ´óÐÍÏîÄ¿ÖУ¬±ØÐëŬÁ¦¼Çס±£ÁôµÄ±äÁ¿Ãû£¬»òΪ¶ÀÒ»ÎÞ¶þµÄÃüÃûʹÓÃÒ»ÖÖͳһµÄ·½·¨¡£

    µ±±àдÄں˴úÂëʱ£¬¼´Ê¹ÊÇ×îСµÄÄ£¿éÒ²»áͬÕû¸öÄÚºËÁ¬½Ó£¬ËùÒÔÕâµÄÈ·ÊǸöÁîÈËÍ·Í´µÄÎÊÌâ¡£ ×îºÃµÄ½â¾ö·½·¨ÊÇÉùÃ÷ÄãµÄ±äÁ¿Îªstatic¾²Ì¬µÄ²¢ÇÒΪÄãµÄ·ûºÅʹÓÃÒ»¸ö¶¨ÒåµÄºÜºÃµÄǰ׺¡£ ´«Í³ÖУ¬Ê¹ÓÃСд×ÖĸµÄÄÚºËǰ׺¡£Èç¹ûÄã²»Ï뽫ËùÓеĶ«Î÷¶¼ÉùÃ÷Ϊstatic¾²Ì¬µÄ£¬ ÁíÒ»¸öÑ¡ÔñÊÇÉùÃ÷Ò»¸ösymbol table£¨·ûºÅ±í£©²¢ÏòÄÚºË×¢²á¡£ÎÒÃǽ«ÔÚÒÔºóÌÖÂÛ¡£

    Îļþ/proc/kallsyms±£´æ×ÅÄÚºËÖªµÀµÄËùÓеķûºÅ£¬Äã¿ÉÒÔ·ÃÎÊËüÃÇ£¬ ÒòΪËüÃÇÊÇÄں˴úÂë¿Õ¼äµÄÒ»²¿·Ö¡£

    ´úÂë¿Õ¼ä
    ÄÚ´æ¹ÜÀíÊÇÒ»¸ö·Ç³£¸´ÔӵĿÎÌâ¡£O'ReillyµÄ¡¶Understanding The Linux Kernel¡·¾ø´ó²¿·Ö¶¼ÔÚ ÌÖÂÛÄÚ´æ¹ÜÀí£¡ÎÒÃÇ ²¢²»×¼±¸×¨×¢ÓÚÄÚ´æ¹ÜÀí£¬µ«ÓÐһЩ¶«Î÷»¹ÊǵÃÖªµÀµÄ¡£

    Èç¹ûÄãûÓÐÈÏÕ濼ÂǹýÄÚ´æÉè¼ÆȱÏÝÒâζ×Åʲô£¬ÄãÒ²Ðí»á¾ªÑȵĻñÖªÒ»¸öÖ¸Õë²¢²»Ö¸ÏòÒ»¸öÈ·ÇÐ µÄÄÚ´æÇøÓò¡£µ±Ò»¸ö½ø³Ì½¨Á¢Ê±£¬ÄÚºËΪËü·ÖÅäÒ»²¿·ÖÈ·ÇеÄʵ¼ÊÄÚ´æ¿Õ¼ä²¢°ÑËü½»¸ø½ø³Ì£¬±»½ø³ÌµÄ ´úÂ룬±äÁ¿£¬¶ÑÕ»ºÍÆäËüһЩ¼ÆËã»úѧµÄר¼Ò²ÅÃ÷°×µÄ¶«Î÷ʹÓÃ[2]¡£ÕâЩÄÚ´æ´Ó$0$ ¿ªÊ¼²¢¿ÉÒÔÀ©Õ¹µ½ÐèÒªµÄµØ·½¡£ÕâЩ ÄÚ´æ¿Õ¼ä²¢²»Öصþ£¬ËùÒÔ¼´Ê¹½ø³Ì·ÃÎÊͬһ¸öÄÚ´æµØÖ·£¬ÀýÈç0xbffff978£¬ ÕæʵµÄÎïÀíÄÚ´æµØÖ·ÆäʵÊDz»Í¬µÄ¡£½ø³Ìʵ¼ÊÖ¸ÏòµÄÊÇÒ»¿é±»·ÖÅäµÄÄÚ´æÖÐÒÔ0xbffff978 ΪƫÒÆÁ¿µÄÒ»¿éÄÚ´æÇøÓò¡£¾ø´ó¶àÊýÇé¿öÏ£¬Ò»¸ö½ø³ÌÏñÆÕͨµÄ"Hello, World"²»¿ÉÒÔ·ÃÎʱðµÄ½ø³ÌµÄ ÄÚ´æ¿Õ¼ä£¬¾¡¹ÜÓÐʵÏÖÕâÖÖ»úÖƵķ½·¨¡£ ÎÒÃǽ«ÔÚÒÔºóÌÖÂÛ¡£

    ÄÚºË×Ô¼ºÒ²ÓÐÄÚ´æ¿Õ¼ä¡£¼ÈȻһ¸öÄÚºËÄ£¿é¿ÉÒÔ¶¯Ì¬µÄ´ÓÄÚºËÖмÓÔغÍжÔØ£¬ËüÆäʵÊǹ²ÏíÄÚºËµÄ ÄÚ´æ¿Õ¼ä¶ø²»ÊÇ×Ô¼ºÓµÓÐ ¶ÀÁ¢µÄÄÚ´æ¿Õ¼ä¡£Òò´Ë£¬Ò»µ©ÄãµÄÄ£¿é¾ßÓÐÄÚ´æÉè¼ÆȱÏÝ£¬Äں˾ÍÊÇÄÚ´æÉè¼ÆȱÏÝÁË¡£ Èç¹ûÄãÔÚ´íÎóµÄ¸²¸ÇÊý¾Ý£¬ÄÇôÄã¾ÍÔÚ ÆÆ»µÄں˵ĴúÂë¡£Õâ±ÈÏÖÔÚÌýÆðÀ´µÄ»¹Ôã¡£ËùÒÔ¾¡Á¿Ð¡ÐĽ÷É÷¡£

    ˳±ãÌáһϣ¬ÒÔÉÏÎÒËùÖ¸³öµÄ¶ÔÓÚÈκε¥ÕûÌåÄں˵IJÙ×÷ϵͳ¶¼ÊÇÕæʵµÄ[3]¡£ Ò²´æÔÚÄ£¿é»¯Î¢Äں˵IJÙ×÷ϵͳ£¬Èç GNU Hurd ºÍ QNX Neutrino¡£

    Device Drivers
    Ò»ÖÖÄÚºËÄ£¿éÊÇÉ豸Çý¶¯³ÌÐò£¬ÎªÊ¹ÓÃÓ²¼þÉ豸ÏñµçÊÓ¿¨ºÍ´®¿Ú¶ø±àд¡£ ÔÚUnixÖУ¬ÈκÎÉ豸¶¼±»µ±×÷·¾¶/dev µÄÉ豸Îļþ´¦Àí£¬²¢Í¨¹ýÕâЩÉ豸ÎļþÌṩ·ÃÎÊÓ²¼þµÄ·½·¨¡£ É豸Çý¶¯ÎªÓû§³ÌÐò ·ÃÎÊÓ²¼þÉ豸¡£¾ÙÀýÀ´Ëµ£¬Éù¿¨É豸Çý¶¯³ÌÐòes1370.o½«»á°ÑÉ豸Îļþ /dev/soundͬÉù¿¨Ó²¼þEnsoniq IS1370ÁªÏµÆðÀ´¡£ ÕâÑùÓû§³ÌÐòÏñ mp3blaster ¾Í¿ÉÒÔͨ¹ý·ÃÎÊÉ豸Îļþ/dev/sound ÔËÐжø²»±ØÖªµÀÄÇÖÖÉù¿¨Ó²¼þ°²×°ÔÚϵͳÉÏ¡£

    Major and Minor Numbers
    ÈÃÎÒÃÇÀ´Ñо¿¼¸¸öÉ豸Îļþ¡£ÕâÀïµÄ¼¸¸öÉ豸Îļþ´ú±í×ÅÒ»¿éÖ÷IDEÓ²ÅÌÉϵÄÍ·Èý¸ö·ÖÇø£º

    # ls -l /dev/hda[1-3]
    brw-rw---- 1 root disk 3, 1 Jul 5 2000 /dev/hda1
    brw-rw---- 1 root disk 3, 2 Jul 5 2000 /dev/hda2
    brw-rw---- 1 root disk 3, 3 Jul 5 2000 /dev/hda3

    ×¢Òâһϱ»¶ººÅ¸ô¿ªµÄÁ½ÁС£µÚÒ»¸öÊý×Ö±»½Ð×öÖ÷É豸ºÅ£¬µÚ¶þ¸ö±»½Ð×ö´ÓÉ豸ºÅ¡£ Ö÷É豸ºÅ¾ö¶¨Ê¹ÓúÎÖÖÉ豸Çý¶¯³ÌÐò¡£ ÿÖÖ²»Í¬µÄÉ豸¶¼±»·ÖÅäÁ˲»Í¬µÄÖ÷É豸ºÅ£» ËùÓоßÓÐÏàͬÖ÷É豸ºÅµÄÉ豸Îļþ¶¼ÊDZ»Í¬Ò»¸öÇý¶¯³ÌÐò¿ØÖÆ¡£ÉÏÃæÀý×ÓÖÐµÄ Ö÷É豸ºÅ¶¼Îª3£¬ ±íʾËüÃǶ¼±»Í¬Ò»¸öÇý¶¯³ÌÐò¿ØÖÆ¡£

    ´ÓÉ豸ºÅÓÃÀ´Çø±ðÇý¶¯³ÌÐò¿ØÖƵĶà¸öÉ豸¡£ÉÏÃæÀý×ÓÖеĴÓÉ豸ºÅ²»ÏàͬÊÇÒòΪËüÃDZ»Ê¶±ðΪ¼¸¸öÉ豸¡£

    É豸±»´ó¸ÅµÄ·ÖΪÁ½Àࣺ×Ö·ûÉ豸ºÍ¿éÉ豸¡£Çø±ðÊÇ¿éÉ豸Óлº³åÇø£¬ËùÒÔËüÃÇ¿ÉÒÔ¶ÔÇëÇó½øÐÐÓÅ»¯ÅÅÐò¡£ Õâ¶Ô´æ´¢É豸ÓÈÆä ÖØÒª£¬ÒòΪ¶ÁдÏàÁÚµÄÎļþ×ܱȶÁдÏà¸ôºÜÔ¶µÄÎļþÒª¿ì¡£ÁíÒ»¸öÇø±ðÊÇ¿éÉ豸ÊäÈëºÍÊä³ö ¶¼ÊÇÒÔÊý¾Ý¿éΪµ¥Î»µÄ£¬µ«ÊÇ×Ö·ûÉ豸 ¾Í¿ÉÒÔ×ÔÓɶÁдÈÎÒâÁ¿µÄ×Ö½Ú¡£´ó²¿·ÖÓ²¼þÉ豸Ϊ×Ö·ûÉ豸£¬ÒòΪËüÃÇ ²»ÐèÒª»º³åÇøºÍÊý¾Ý²»ÊÇ°´¿éÀ´´«ÊäµÄ¡£Äã¿ÉÒÔͨ¹ýÃüÁîls -lÊä³öµÄÍ·Ò»¸ö×Öĸʶ±ðÒ»¸ö É豸ΪºÎÖÖÉ豸¡£Èç¹ûÊÇ'b' ¾ÍÊÇ¿éÉ豸£¬Èç¹ûÊÇ'c'¾ÍÊÇ×Ö·ûÉ豸¡£ÒÔÉÏÄã¿´µ½µÄÊÇ¿éÉ豸¡£Õâ¶ù»¹ÓÐһЩ ×Ö·ûÉ豸Îļþ£¨´®¿Ú£©£º

    crw-rw---- 1 root dial 4, 64 Feb 18 23:34 /dev/ttyS0
    crw-r----- 1 root dial 4, 65 Nov 17 10:26 /dev/ttyS1
    crw-rw---- 1 root dial 4, 66 Jul 5 2000 /dev/ttyS2
    crw-rw---- 1 root dial 4, 67 Jul 5 2000 /dev/ttyS3

    Èç¹ûÄãÏë¿´Ò»ÏÂÒÑ·ÖÅäµÄÖ÷É豸ºÅ¶¼ÊÇЩʲôÉ豸¿ÉÒÔ¿´Ò»ÏÂÎļþ /usr/src/linux/Documentation/devices.txt¡£

    ϵͳ°²×°Ê±£¬ËùÓеÄÕâЩÉ豸Îļþ¶¼ÊÇÓÉÃüÁîmknod½¨Á¢µÄ¡£È¥½¨Á¢Ò»¸öеÄÃû½Ð coffee'£¬Ö÷É豸ºÅΪ12ºÍ´ÓÉ豸ºÅΪ2µÄÉ豸Îļþ£¬Ö»Òª¼òµ¥µÄ Ö´ÐÐÃüÁîmknod /dev/coffee c 12 2¡£Äã²¢²»ÊDZØÐ뽫É豸Îļþ·ÅÔÚĿ¼ /devÖУ¬ÕâÖ»ÊÇÒ»¸ö´«Í³¡£Linus±¾ÈËÊÇÕâÑù×öµÄ£¬ËùÒÔÄã×îºÃÒ²²»ÀýÍâ¡£ µ«ÊÇ£¬µ±Äã²âÊÔÒ»¸öÄ£¿éʱ£¬ÔÚ¹¤×÷Ŀ¼½¨Á¢Ò»¸öÉ豸ÎļþÒ²²»´í¡£ Ö»Òª±£Ö¤Íê³Éºó½«Ëü·ÅÔÚÇý¶¯³ÌÐòÕҵõ½µÄµØ·½¡£

    ÎÒ»¹ÏëÉùÃ÷ÔÚÒÔÉÏÌÖÂÛÖÐÒþº¬µÄ¼¸µã¡£µ±ÏµÍ³·ÃÎÊÒ»¸öϵͳÎļþʱ£¬ ϵͳÄÚºËֻʹÓÃÖ÷É豸ºÅÀ´Çø±ðÉ豸ÀàÐͺ;ö¶¨Ê¹ÓúÎÖÖÄÚºËÄ£¿é¡£ÏµÍ³ Äں˲¢²»ÐèÒªÖªµÀ´ÓÉ豸ºÅ¡£ÄÚºËÄ£¿éÇý¶¯±¾Éí²Å¹Ø×¢´ÓÉ豸ºÅ£¬²¢ÓÃÖ®À´ Çø±ðÆä²Ù×ݵIJ»Í¬É豸¡£

    ÁíÍ⣬ÎÒÕâ¶ùÌáµ½µÄÓ²¼þÊDZÈÄÇÖÖ¿ÉÒÔÎÕÔÚÊÖÀïµÄPCI¿¨ÉÔ΢³éÏóÒ»µãµÄ¶«Î÷¡£¿´Ò»ÏÂÏÂÃæµÄÁ½¸öÉ豸Îļþ£º

    % ls -l /dev/fd0 /dev/fd0u1680
    brwxrwxrwx 1 root floppy 2, 0 Jul 5 2000 /dev/fd0
    brw-rw---- 1 root floppy 2, 44 Jul 5 2000 /dev/fd0u1680

    ÄãÏÖÔÚÁ¢¼´Ã÷°×ÕâÊÇ¿ìÉ豸µÄÉ豸Îļþ²¢ÇÒËüÃÇÊÇÓÐÏàͬµÄÇý¶¯ÄÚºËÄ£¿éÀ´²Ù×Ý £¨Ö÷É豸ºÅ¶¼Îª2)£©¡£ÄãÒ²ÐíÒ²Òâʶµ½ËüÃǶ¼ÊÇÄãµÄÈíÅÌÇý¶¯Æ÷£¬ ¼´Ê¹Äãʵ¼ÊÉÏÖ»ÓÐÒ»¸öÈíÅÌÇý¶¯Æ÷¡£ÎªÊ²Ã´ÊÇÁ½¸öÉ豸Îļþ£¿ÒòΪËüÃÇÆäÖеÄÒ»¸ö´ú±í×Å ÄãµÄ1.44 MBÈÝÁ¿µÄÈíÇý£¬ÁíÒ»¸ö´ú±í×ÅÄãµÄ1.68 MBÈÝÁ¿µÄ£¬±»Ä³Ð©È˳ÆΪ¡°³¬¼¶¸ñʽ»¯¡±µÄÈíÇý¡£ Õâ¾ÍÊÇÒ»¸ö²»Í¬µÄ´ÓÉ豸ºÅ´ú±í×ÅÏàͬӲ¼þÉ豸µÄÀý×Ó¡£ÇëÇå³þµÄÒâʶµ½ÎÒÃÇÌáµ½µÄÓ²¼þÓÐʱ ¿ÉÄÜÊǷdz£³éÏóµÄ¡£

    Notes
    [1] ÕâÊÇÒ»¸öÈ¥¸ú×Ù³ÌÐò¾¿¾¹ÔÚ×öʲôµÄ·Ç³£ÓмÛÖµµÄ¹¤¾ß¡£

    [2] ÎÒÊÇÎïÀíרҵµÄ£¬ ¶ø²»ÊÇÖ÷ÐÞ¼ÆËã»ú¡£

    [3] ÕⲻͬÓÚ½«ËùÓеÄÄÚºËÄ£¿é±àÒë½øÄںˣ¬µ«Òâ˼ȷʵÊÇÒ»ÑùµÄ¡£

  17. febspeolal ÓÚ 2006-11-09 01:08:24·¢±í:

    Chapter 2. Hello World
    Table of Contents
    Hello, World (part 1): ×î¼òµ¥µÄÄÚºËÄ£¿é
    ±àÒëÄÚºËÄ£¿é
    Hello World (part 2)
    Hello World (part 3): ¹ØÓÚ__initºÍ__exitºê
    Hello World (part 4): ÄÚºËÄ£¿éÖ¤ÊéºÍÄÚºËÄ£¿éÎĵµËµÃ÷
    ´ÓÃüÁîÐд«µÝ²ÎÊý¸øÄÚºËÄ£¿é
    Óɶà¸öÎļþ¹¹³ÉµÄÄÚºËÄ£¿é
    ΪÒѱàÒëµÄÄں˱àÒëÄ£¿é
    Hello, World (part 1): ×î¼òµ¥µÄÄÚºËÄ£¿é
    µ±µÚÒ»¸ö¶´Ñ¨³ÌÐòÔ±ÔÚµÚһ̨¶´Ñ¨¼ÆËã»úµÄǽÉÏÉÏÔäдµÚÒ»¸ö³ÌÐòʱ£¬ ÕâÊÇÒ»¸öÔÚÁçÑòƤÉÏÊä³ö`Hello, world'µÄ×Ö·û´®¡£ÂÞÂíµÄ±à³ÌÊé¼®ÉÏÊÇÒÔ `Salut, Mundi'ÕâÑùµÄ³ÌÐò¿ªÊ¼µÄ¡£ ÎÒ²»Ã÷°×ÈËÃÇΪʲôҪÆÆ»µÕâ¸ö´«Í³£¬ µ«ÎÒÈÏΪ»¹ÊDz»Ã÷°×ΪºÃ¡£ÎÒÃǽ«´Ó±àдһϵÁеÄ`Hello, world'Ä£¿é¿ªÊ¼£¬ Ò»²½²½Õ¹Ê¾±àдÄÚºËÄ£¿éµÄ»ù´¡µÄ·½·½ÃæÃæ¡£

    Õâ¿ÉÄÜÊÇÒ»¸ö×î¼òµ¥µÄÄ£¿éÁË¡£Ïȱð¼±×űàÒëËü¡£ÎÒÃǽ«ÔÚÏÂÕÂÄ£¿é±àÒëµÄÕ½ڽéÉÜÏà¹ØÄÚÈÝ¡£

    Example 2-1. hello-1.c

    /*
    * hello-1.c - The simplest kernel module.
    */
    #include /* Needed by all modules */
    #include /* Needed for KERN_ALERT */

    int init_module(void)
    {
    printk("<1>Hello world 1.\n" );

    /*
    * A non 0 return means init_module failed; module can't be loaded.
    */
    return 0;
    }

    void cleanup_module(void)
    {
    printk(KERN_ALERT "Goodbye world 1.\n" );
    }
    Ò»¸öÄÚºËÄ£¿éÓ¦¸ÃÖÁÉÙ°üº¬Á½¸öº¯Êý¡£Ò»¸ö¡°¿ªÊ¼¡±(³õʼ»¯)µÄº¯Êý±»³ÆΪinit_module() »¹ÓÐÒ»¸ö¡°½áÊø¡± (¸ÉһЩÊÕβÇåÀíµÄ¹¤×÷)µÄº¯Êý±»³ÆΪcleanup_module() £¬µ±ÄÚºËÄ£¿é±»rmmodжÔØʱ±»Ö´ÐС£Êµ¼ÊÉÏ£¬´ÓÄں˰汾2.3.13¿ªÊ¼ÕâÖÖÇé¿öÓÐЩ¸Ä±ä¡£ Äã¿ÉÒÔΪÄãµÄ¿ªÊ¼ºÍ½áÊøº¯ÊýÆðÈÎÒâµÄÃû×Ö¡£ Ä㽫ÔÚÒÔºóѧϰÈçºÎʵÏÖÕâÒ»µãthe Section called Hello World (part 2)¡£ ʵ¼ÊÉÏ£¬Õâ¸öз½·¨Ê±ÍƼöµÄʵÏÖ·½·¨¡£µ«ÊÇ£¬Ðí¶àÈËÈÔȻʹinit_module()ºÍ cleanup_module()×÷ΪËûÃǵĿªÊ¼ºÍ½áÊøº¯Êý¡£

    Ò»°ã£¬init_module()ҪôÏòÄÚºË×¢²áËü¿ÉÒÔ´¦ÀíµÄÊÂÎҪôÓÃ×Ô¼ºµÄ´úÂë Ìæ´úij¸öÄں˺¯Êý(´úÂëͨ³£ÕâÑù×öÈ»ºóÔÙÈ¥µ÷ÓÃÔ­Ïȵĺ¯Êý´úÂë)¡£º¯Êý cleanup_module()Ó¦¸Ã³·ÏûÈκÎinit_module()×öµÄÊ£¬´Ó¶ø ÄÚºËÄ£¿é¿ÉÒÔ±»°²È«µÄжÔØ¡£

    ×îºó£¬ÈÎÒ»¸öÄÚºËÄ£¿éÐèÒª°üº¬linux/module.h¡£ ÎÒÃǽö½öÐèÒª°üº¬ linux/kernel.hµ±ÐèҪʹÓà printk()¼Ç¼¼¶±ðµÄºêÀ©Õ¹Ê±KERN_ALERT£¬Ïà¹ØÄÚÈݽ«ÔÚthe Section called ½éÉÜprintk()ÖнéÉÜ¡£

    ½éÉÜprintk()
    ²»¹ÜÄã¿ÉÄÜÔõôÏ룬printk()²¢²»ÊÇÉè¼ÆÓÃÀ´Í¬Óû§½»»¥µÄ£¬ËäÈ»ÎÒÃÇÔÚ hello-1¾ÍÊdzöÓÚÕâÑùµÄÄ¿µÄʹÓÃËü£¡Ëüʵ¼ÊÉÏÊÇΪÄÚºËÌṩÈÕÖ¾¹¦ÄÜ£¬ ¼Ç¼ÄÚºËÐÅÏ¢»òÓÃÀ´¸ø³ö¾¯¸æ¡£Òò´Ë£¬Ã¿¸öprintk() ÉùÃ÷¶¼»á´øÒ»¸öÓÅÏȼ¶£¬¾ÍÏñÄã¿´µ½µÄ<1>ºÍKERN_ALERT ÄÇÑù¡£ÄÚºË×ܹ²¶¨ÒåÁ˰˸öÓÅÏȼ¶µÄºê£¬ ËùÒÔÄã²»±ØʹÓûÞɬµÄÊý×Ö´úÂ룬²¢ÇÒÄã¿ÉÒÔ´ÓÎļþ linux/kernel.h²é¿´ÕâЩºêºÍËüÃǵÄÒâÒå¡£Èç¹ûÄã ²»Ö¸Ã÷ÓÅÏȼ¶£¬Ä¬ÈϵÄÓÅÏȼ¶DEFAULT_MESSAGE_LOGLEVEL½«±»²ÉÓá£

    ÔĶÁÒ»ÏÂÕâЩÓÅÏȼ¶µÄºê¡£Í·ÎļþͬʱҲÃèÊöÁËÿ¸öÓÅÏȼ¶µÄÒâÒå¡£ÔÚʵ¼ÊÖУ¬ ʹÓúê¶ø²»ÒªÊ¹ÓÃÊý×Ö£¬¾ÍÏñ<4>¡£×ÜÊÇʹÓú꣬¾ÍÏñ KERN_WARNING¡£

    µ±ÓÅÏȼ¶µÍÓÚint console_loglevel£¬ÐÅÏ¢½«Ö±½Ó´òÓ¡ÔÚÄãµÄÖÕ¶ËÉÏ¡£Èç¹ûͬʱ syslogdºÍklogd¶¼ÔÚÔËÐУ¬ÐÅϢҲͬʱÌí¼ÓÔÚÎļþ /var/log/messages£¬¶ø²»¹ÜÊÇ·ñÏÔʾÔÚ¿ØÖÆ̨ÉÏÓë·ñ¡£ÎÒÃÇʹÓÃÏñ KERN_ALERTÕâÑùµÄ¸ßÓÅÏȼ¶£¬À´È·±£printk()½«ÐÅÏ¢Êä³öµ½ ¿ØÖÆ̨¶ø²»ÊÇÖ»ÊÇÌí¼Óµ½ÈÕÖ¾ÎļþÖС£ µ±Äã±àдÕæÕýµÄʵÓõÄÄ£¿éʱ£¬ÄãÓ¦¸ÃÕë¶Ô¿ÉÄÜÓöµ½µÄÇé¿öʹÓÃºÏ ÊʵÄÓÅÏȼ¶¡£
    ±àÒëÄÚºËÄ£¿é
    ÄÚºËÄ£¿éÔÚÓÃgcc±àÒëʱÐèҪʹÓÃÌض¨µÄ²ÎÊý¡£ÁíÍ⣬һЩºêͬÑùÐèÒª¶¨Òå¡£ ÕâÊÇÒòΪÔÚ±àÒë³É¿ÉÖ´ÐÐÎļþºÍÄÚºËÄ£¿éʱ£¬ ÄÚºËÍ·ÎļþÆðµÄ×÷ÓÃÊDz»Í¬µÄ¡£ ÒÔÍùµÄÄں˰汾ÐèÒªÎÒÃÇÈ¥ÔÚMakefileÖÐÊÖ¶¯ÉèÖÃÕâЩÉ趨¡£¾¡¹ÜÕâЩMakefileÊÇ°´Ä¿Â¼·Ö²ã´Î °²Åŵģ¬µ«ÊÇÕâÆäÖÐÓÐÐí¶à¶àÓàµÄÖظ´²¢µ¼Ö´úÂëÊ÷´ó¶øÄÑÒÔά»¤¡£ ÐÒÔ˵ÄÊÇ£¬Ò»ÖÖ³ÆΪkbuildµÄз½·¨±»ÒýÈ룬ÏÖÔÚÍⲿµÄ¿É¼ÓÔØÄÚºËÄ£¿éµÄ±àÒëµÄ·½·¨ÒѾ­Í¬Äں˱àÒëͳһÆðÀ´¡£ÏëÁ˽â¸ü¶àµÄ±à Òë·ÇÄں˴úÂëÊ÷ÖеÄÄ£¿é(¾ÍÏñÎÒÃǽ«Òª±àдµÄ)Çë²Î¿¼°ïÖúÎļþlinux/Documentation/kbuild/modules.txt¡£

    ÏÖÔÚÈÃÎÒÃÇ¿´Ò»¸ö±àÒëÃû×Ö½Ð×öhello-1.cµÄÄ£¿éµÄ¼òµ¥µÄMakefileÎļþ£º

    Example 2-2. Ò»¸ö»ù±¾µÄMakefile

    obj-m += hello-1.o

    ÏÖÔÚÄã¿ÉÒÔͨ¹ýÖ´ÐÐÃüÁî make -C /usr/src/linux-`uname -r` SUBDIRS=$PWD modules ±àÒëÄ£¿é¡£ ÄãÓ¦¸ÃµÃµ½Í¬ÏÂÃæÀàËƵÄÆÁÄ»Êä³ö£º

    [root@pcsenonsrv test_module]# make -C /usr/src/linux-`uname -r` SUBDIRS=$PWD modules
    make: Entering directory `/usr/src/linux-2.6.x
    CC [M] /root/test_module/hello-1.o
    Building modules, stage 2.
    MODPOST
    CC /root/test_module/hello-1.mod.o
    LD [M] /root/test_module/hello-1.ko
    make: Leaving directory `/usr/src/linux-2.6.x

    Çë×¢Òâ2.6µÄÄÚºËÏÖÔÚÒýÈëÒ»ÖÖеÄÄÚºËÄ£¿éÃüÃû¹æ·¶£ºÄÚºËÄ£¿éÏÖÔÚʹÓÃ.koµÄÎļþºó׺(´úÌæ ÒÔÍùµÄ.oºó׺)£¬ÕâÑùÄÚºËÄ£¿é¾Í¿ÉÒÔͬÆÕͨµÄÄ¿±êÎļþÇø±ð¿ª¡£¸üÏêϸµÄÎĵµÇë²Î¿¼ linux/Documentation/kbuild/makefiles.txt¡£ÔÚÑо¿Makefile֮ǰÇëÈ·ÈÏÄãÒѾ­²Î¿¼ÁËÕâЩÎĵµ¡£

    ÏÖÔÚÊÇʹÓÃinsmod ./hello-1.koÃüÁî¼ÓÔظÃÄ£¿éµÄʱºòÁË(ºöÂÔÈκÎÄã¿´µ½µÄ¹ØÓÚÄÚºËÎÛȾµÄÊä³ö ÏÔʾ£¬ÎÒÃǽ«ÔÚÒÔºó½éÉÜÏà¹ØÄÚÈÝ)¡£

    ËùÓÐÒѾ­±»¼ÓÔصÄÄÚºËÄ£¿é¶¼ÂÞÁÐÔÚÎļþ/proc/modulesÖС£catÒ»ÏÂÕâ¸öÎļþ¿´Ò»ÏÂÄãµÄÄ£¿éÊÇ·ñÕæµÄ ³ÉΪÄں˵ÄÒ»²¿·ÖÁË¡£Èç¹ûÊÇ£¬×£ºØÄ㣡ÄãÏÖÔÚÒѾ­ÊÇÄÚºËÄ£¿éµÄ×÷ÕßÁË¡£µ±ÄãµÄÐÂÏʾ¢¹ýÈ¥ºó£¬Ê¹ÓÃÃüÁî rmmod hello-1.жÔØÄ£¿é¡£ÔÙ¿´Ò»ÏÂ/var/log/messagesÎļþµÄÄÚÈÝÊÇ·ñÓÐÏà¹ØµÄÈÕÖ¾ÄÚÈÝ¡£

    Õâ¶ùÊÇÁíÒ»¸öÁ·Ï°¡£¿´µ½ÁËÔÚÉùÃ÷ init_module()ÉϵÄ×¢ÊÍÂð? ¸Ä±ä·µ»ØÖµ·ÇÁ㣬ÖØбàÒëÔÙ¼ÓÔØ£¬·¢ÉúÁËʲô£¿
    Hello World (part 2)
    ÔÚÄÚºËLinux 2.4ÖУ¬Äã¿ÉÒÔΪÄãµÄÄ£¿éµÄ¡°¿ªÊ¼¡±ºÍ¡°½áÊø¡±º¯ÊýÆðÈÎÒâµÄÃû×Ö¡£ËüÃDz»ÔÙ±ØÐëʹÓà init_module()ºÍcleanup_module()µÄÃû×Ö¡£Õâ¿ÉÒÔͨ¹ýºê module_init()ºÍmodule_exit()ʵÏÖ¡£ÕâЩºêÔÚÍ·Îļþlinux/init.h¶¨Ò塣ΨһÐèҪעÒâµÄµØ·½ÊǺ¯Êý±ØÐëÔÚºêµÄʹÓÃÇ°¶¨Ò壬·ñÔò»áÓбàÒë ´íÎó¡£ÏÂÃæ¾ÍÊÇÒ»¸öÀý×Ó¡£

    Example 2-3. hello-2.c

    /*
    * hello-2.c - Demonstrating the module_init() and module_exit() macros.
    * This is preferred over using init_module() and cleanup_module().
    */
    #include /* Needed by all modules */
    #include /* Needed for KERN_ALERT */
    #include /* Needed for the macros */

    static int __init hello_2_init(void)
    {
    printk(KERN_ALERT "Hello, world 2\n" );
    return 0;
    }

    static void __exit hello_2_exit(void)
    {
    printk(KERN_ALERT "Goodbye, world 2\n" );
    }

    module_init(hello_2_init);
    module_exit(hello_2_exit);
    ÏÖÔÚÎÒÃÇÒѾ­Ð´¹ýÁ½¸öÕæÕýµÄÄ£¿éÁË¡£Ìí¼Ó±àÒëÁíÒ»¸öÄ£¿éµÄÑ¡ÏîÊ®·Ö¼òµ¥£¬ÈçÏ£º

    Example 2-4. Á½¸öÄÚºËÄ£¿éʹÓõÄMakefile

    obj-m += hello-1.o
    obj-m += hello-2.o
    ÏÖÔÚÈÃÎÒÃÇÀ´Ñо¿Ò»ÏÂlinux/drivers/char/MakefileÕâ¸öʵ¼ÊÖеÄÀý×Ó¡£¾ÍÈçͬÄã¿´µ½µÄ£¬ һЩ±»±àÒë½øÄÚºË (obj-y)£¬µ«ÊÇÕâЩobj-mÄÄÀïÈ¥ÁËÄØ£¿¶ÔÓÚÊìϤshell½Å±¾µÄÈËÕâ²»ÄÑÀí½â¡£ÕâЩÔÚMakefileÖÐËæ´¦¿É¼û µÄobj-$(CONFIG_FOO)µÄÖ¸Á»áÔÚCONFIG_FOO±»ÉèÖúóÀ©Õ¹ÎªÄãÊìϤµÄobj-y»òobj-m¡£ÕâÆäʵ¾ÍÊÇÄãÔÚʹÓà make menuconfig±àÒëÄÚºËʱÉú³ÉµÄlinux/.configÖÐÉèÖõĶ«Î÷¡£
    Hello World (part 3): ¹ØÓÚ__initºÍ__exitºê
    ÕâÀïչʾÁËÄÚºË2.2ÒÔºóÒýÈëµÄÒ»¸öÐÂÌØÐÔ¡£×¢ÒâÔÚ¸ºÔð¡°³õʼ»¯¡±ºÍ¡°ÇåÀíÊÕβ¡±µÄº¯Êý¶¨Òå´¦µÄ±ä»¯¡£ºê __initµÄʹÓûáÔÚ³õʼ»¯Íê³Éºó¶ªÆú¸Ãº¯Êý²¢ÊÕ»ØËùÕ¼Äڴ棬Èç¹û¸ÃÄ£¿é±»±àÒë½øÄںˣ¬¶ø²»ÊǶ¯Ì¬¼ÓÔØ¡£

    ºê__initdataͬ__init ÀàËÆ£¬Ö»²»¹ý¶Ô±äÁ¿ÓÐЧ¡£

    ºê__exit½«ºöÂÔ¡°ÇåÀíÊÕβ¡±µÄº¯ÊýÈç¹û¸ÃÄ£¿é±»±àÒë½øÄںˡ£Í¬ºê __exitÒ»Ñù£¬¶Ô¶¯Ì¬¼ÓÔØÄ£¿éÊÇÎÞЧµÄ¡£ÕâºÜÈÝÒ×Àí½â¡£±àÒë½øÄں˵ÄÄ£¿é ÊÇûÓÐÇåÀíÊÕβ¹¤×÷µÄ, ¶ø¶¯Ì¬¼ÓÔصÄÈ´ÐèÒª×Ô¼ºÍê³ÉÕâЩ¹¤×÷¡£

    ÕâЩºêÔÚÍ·Îļþlinux/init.h¶¨Ò壬ÓÃÀ´ÊÍ·ÅÄÚºËÕ¼ÓõÄÄÚ´æ¡£ µ±ÄãÔÚÆô¶¯Ê±¿´µ½ÕâÑùµÄFreeing unused kernel memory: 236k freedÄÚºËÊä³ö£¬ÉÏÃæµÄ ÄÇЩÕýÊÇÄÚºËËùÊͷŵġ£

    Example 2-5. hello-3.c

    /*
    * hello-3.c - Illustrating the __init, __initdata and __exit macros.
    */
    #include /* Needed by all modules */
    #include /* Needed for KERN_ALERT */
    #include /* Needed for the macros */

    static int hello3_data __initdata = 3;

    static int __init hello_3_init(void)
    {
    printk(KERN_ALERT "Hello, world %d\n", hello3_data);
    return 0;
    }

    static void __exit hello_3_exit(void)
    {
    printk(KERN_ALERT "Goodbye, world 3\n" );
    }

    module_init(hello_3_init);
    module_exit(hello_3_exit);
    Hello World (part 4): ÄÚºËÄ£¿éÖ¤ÊéºÍÄÚºËÄ£¿éÎĵµËµÃ÷
    Èç¹ûÄãÔÚʹÓÃ2.4»ò¸üеÄÄںˣ¬µ±Äã¼ÓÔØÄãµÄÄ£¿éʱ£¬ÄãÒ²Ðí×¢Òâµ½ÁËÕâЩÊä³öÐÅÏ¢£º

    # insmod hello-3.o
    Warning: loading hello-3.o will taint the kernel: no license
    See http://www.tux.org/lkml/#export-tainted for information about tainted modules
    Hello, world 3
    Module hello-3 loaded, with warnings

    ÔÚ2.4»ò¸üеÄÄÚºËÖУ¬Ò»ÖÖʶ±ð´úÂëÊÇ·ñÔÚGPLÐí¿ÉÏ·¢²¼µÄ»úÖƱ»ÒýÈ룬 Òò´ËÈËÃÇ¿ÉÒÔÔÚʹÓ÷ǹ«¿ªµÄÔ´´úÂë²úƷʱµÃµ½¾¯¸æ¡£Õâͨ¹ýÔÚÏÂÒ»ÕÂչʾµÄºê MODULE_LICENSE()µ±ÄãÉèÖÃÔÚGPLÖ¤ÊéÏ·¢²¼ÄãµÄ´úÂëʱ£¬ Äã¿ÉÒÔÈ¡ÏûÕâЩ¾¯¸æ¡£ÕâÖÖÖ¤Êé»úÖÆÔÚÍ·Îļþlinux/module.h ʵÏÖ£¬Í¬Ê±»¹ÓÐһЩÏà¹ØÎĵµÐÅÏ¢¡£

    /*
    * The following license idents are currently accepted as indicating free
    * software modules
    *
    * "GPL " [GNU Public License v2 or later]
    * "GPL v2 " [GNU Public License v2]
    * "GPL and additional rights" [GNU Public License v2 rights and more]
    * "Dual BSD/GPL " [GNU Public License v2
    * or BSD license choice]
    * "Dual MPL/GPL " [GNU Public License v2
    * or Mozilla license choice]
    *
    * The following other idents are available
    *
    * " Proprietary" [Non free products]
    *
    * There are dual licensed components, but when running with Linux it is the
    * GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
    * is a GPL combined work.
    *
    * This exists for several reasons
    * 1. So modinfo can show license info for users wanting to vet their setup
    * is free
    * 2. So the community can ignore bug reports including proprietary modules
    * 3. So vendors can do likewise based on their own policies
    */

    ÀàËƵģ¬ºêMODULE_DESCRIPTION()ÓÃÀ´ÃèÊöÄ£¿éµÄÓÃ;¡£ ºêMODULE_AUTHOR()ÓÃÀ´ÉùÃ÷Ä£¿éµÄ×÷Õß¡£ºêMODULE_SUPPORTED_DEVICE() ÉùÃ÷Ä£¿éÖ§³ÖµÄÉ豸¡£

    ÕâЩºê¶¼ÔÚÍ·Îļþlinux/module.h¶¨Ò壬 ²¢ÇÒÄں˱¾Éí²¢²»Ê¹ÓÃÕâЩºê¡£ËüÃÇÖ»ÊÇÓÃÀ´Ìṩʶ±ðÐÅÏ¢£¬¿ÉÓù¤¾ß³ÌÐòÏñobjdump²é¿´¡£ ×÷Ϊһ¸öÁ·Ï°£¬Ê¹ÓÃgrep´ÓĿ¼linux/drivers¿´Ò»¿´ÕâЩģ¿éµÄ×÷ÕßÊÇÈçºÎ ΪËûÃǵÄÄ£¿éÌṩʶ±ðÐÅÏ¢ºÍµµ°¸µÄ¡£

    Example 2-6. hello-4.c

    /*
    * hello-4.c - Demonstrates module documentation.
    */
    #include
    #include
    #include
    #define DRIVER_AUTHOR " Peter Jay Salzman <p@dirac.org>"
    #define DRIVER_DESC "A sample driver"

    static int __init init_hello_4(void)
    {
    printk(KERN_ALERT "Hello, world 4\n" );
    return 0;
    }

    static void __exit cleanup_hello_4(void)
    {
    printk(KERN_ALERT "Goodbye, world 4\n" );
    }

    module_init(init_hello_4);
    module_exit(cleanup_hello_4);

    /*
    * You can use strings, like this:
    */

    /*
    * Get rid of taint message by declaring code as GPL.
    */
    MODULE_LICENSE("GPL" );

    /*
    * Or with defines, like this:
    */
    MODULE_AUTHOR(DRIVER_AUTHOR ); /* Who wrote this module? */
    MODULE_DESCRIPTION(DRIVER_DESC ); /* What does this module do */

    /*
    * This module uses /dev/testdevice. The MODULE_SUPPORTED_DEVICE macro might
    * be used in the future to help automatic configuration of modules, but is
    * currently unused other than for documentation purposes.
    */
    MODULE_SUPPORTED_DEVICE("testdevice" );
    ´ÓÃüÁîÐд«µÝ²ÎÊý¸øÄÚºËÄ£¿é
    Ä£¿éÒ²¿ÉÒÔ´ÓÃüÁîÐлñÈ¡²ÎÊý¡£µ«²»ÊÇͨ¹ýÒÔÇ°ÄãÏ°¹ßµÄargc/argv¡£

    Òª´«µÝ²ÎÊý¸øÄ£¿é£¬Ê×ÏȽ«»ñÈ¡²ÎÊýÖµµÄ±äÁ¿ÉùÃ÷Ϊȫ¾Ö±äÁ¿¡£È»ºóʹÓúêMODULE_PARM()(ÔÚÍ·Îļþlinux/module.h)¡£ÔËÐÐʱ£¬insmod½«¸ø±äÁ¿¸³ÓèÃüÁîÐеIJÎÊý£¬Èçͬ ./insmod mymodule.o myvariable=5¡£ÎªÊ¹´úÂëÇåÎú£¬±äÁ¿µÄÉùÃ÷ºÍºê¶¼Ó¦¸Ã·ÅÔÚ Ä£¿é´úÂëµÄ¿ªÊ¼²¿·Ö¡£ÒÔϵĴúÂë·¶ÀýÒ²Ðí½«±ÈÎÒ¹«ÈϲµÄ½â˵¸üºÃ¡£

    ºêMODULE_PARM()ÐèÒªÁ½¸ö²ÎÊý£¬±äÁ¿µÄÃû×ÖºÍÆäÀàÐÍ¡£Ö§³ÖµÄÀàÐÍÓÐ" b": ±ÈÌØÐÍ£¬"h": ¶ÌÕûÐÍ, "i": ÕûÊýÐÍ£¬" l: ³¤ÕûÐÍºÍ "s": ×Ö·û´®ÐÍ,ÆäÖÐÕýÊýÐͼȿÉΪsignedÒ²¿ÉΪunsigned¡£ ×Ö·û´®ÀàÐÍÓ¦¸ÃÉùÃ÷Ϊ"char *"ÕâÑùinsmod¾Í¿ÉÒÔΪËüÃÇ·ÖÅäÄÚ´æ¿Õ¼ä¡£ÄãÓ¦¸Ã×ÜÊÇΪÄãµÄ±äÁ¿¸³³õÖµ¡£ ÕâÊÇÄں˱à³Ì£¬´úÂëÒª±àдµÄÊ®·Ö½÷É÷¡£¾Ù¸öÀý×Ó£º

    int myint = 3;
    char *mystr;

    MODULE_PARM(myint, "i" );
    MODULE_PARM(mystr, "s" );

    Êý×éͬÑù±»Ö§³Ö¡£ÔÚºêMODULE_PARMÖÐÔÚÀàÐÍ·ûºÅÇ°ÃæµÄÕûÐÍÖµÒâζ×ÅÒ»¸öÖ¸¶¨ÁË×î´ó³¤¶ÈµÄÊý×é¡£ ÓÃ'-'¸ô¿ªµÄÁ½¸öÊý×ÖÔò·Ö±ðÒâζ×Å×îСºÍ×î´ó³¤¶È¡£ÏÂÃæµÄÀý×ÓÖУ¬¾ÍÉùÃ÷ÁËÒ»¸ö×îС³¤¶ÈΪ2,×î´ó³¤¶ÈΪ4µÄÕûÐÎÊý×é¡£

    int myshortArray[4];
    MODULE_PARM (myintArray, "3-9i" );

    ½«³õʼֵÉèΪȱʡʹÓõÄIO¶Ë¿Ú»òIOÄÚ´æÊÇÒ»¸ö²»´íµÄ×÷·¨¡£Èç¹ûÕâЩ±äÁ¿ÓÐȱʡֵ£¬Ôò¿ÉÒÔ½øÐÐ×Ô¶¯É豸¼ì²â£¬ ·ñÔò±£³Öµ±Ç°ÉèÖõÄÖµ¡£ÎÒÃǽ«ÔÚºóÐøÕ½ڽâÊÍÇå³þÏà¹ØÄÚÈÝ¡£ÔÚÕâÀïÎÒÖ»ÊÇÑÝʾÈçºÎÏòÒ»¸öÄ£¿é´«µÝ²ÎÊý¡£

    ×îºó£¬»¹ÓÐÕâÑùÒ»¸öºê£¬MODULE_PARM_DESC()±»ÓÃÀ´×¢½â¸ÃÄ£¿é¿ÉÒÔ½ÓÊյIJÎÊý¡£¸Ãºê Á½¸ö²ÎÊý£º±äÁ¿ÃûºÍÒ»¸ö¸ñʽ×ÔÓɵĶԸñäÁ¿µÄÃèÊö¡£

    Example 2-7. hello-5.c

    /*
    * hello-5.c - Demonstrates command line argument passing to a module.
    */
    #include
    #include
    #include
    #include
    #include

    MODULE_LICENSE("GPL" );
    MODULE_AUTHOR(" Peter Jay Salzman" );

    static short int myshort = 1;
    static int myint = 420;
    static long int mylong = 9999;
    static char *mystring = "blah";

    /*
    * module_param(foo, int, 0000)
    * The first param is the parameters name
    * The second param is it's data type
    * The final argument is the permissions bits,
    * for exposing parameters in sysfs (if non-zero) at a later stage.
    */

    module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    MODULE_PARM_DESC(myshort, "A short integer" );
    module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    MODULE_PARM_DESC(myint, "An integer" );
    module_param(mylong, long, S_IRUSR);
    MODULE_PARM_DESC(mylong, "A long integer" );
    module_param(mystring, charp, 0000);
    MODULE_PARM_DESC(mystring, "A character string" );

    static int __init hello_5_init(void)
    {
    printk(KERN_ALERT "Hello, world 5\n=============\n" );
    printk(KERN_ALERT "myshort is a short integer: %hd\n", myshort);
    printk(KERN_ALERT "myint is an integer: %d\n", myint);
    printk(KERN_ALERT "mylong is a long integer: %ld\n", mylong);
    printk(KERN_ALERT "mystring is a string: %s\n", mystring);
    return 0;
    }

    static void __exit hello_5_exit(void)
    {
    printk(KERN_ALERT "Goodbye, world 5\n" );
    }

    module_init(hello_5_init);
    module_exit(hello_5_exit);
    ÎÒ½¨ÒéÓÃÏÂÃæµÄ·½·¨ÊµÑéÄãµÄÄ£¿é£º

    satan# insmod hello-5.o mystring="bebop" mybyte=255 myintArray=-1
    mybyte is an 8 bit integer: 255
    myshort is a short integer: 1
    myint is an integer: 20
    mylong is a long integer: 9999
    mystring is a string: bebop
    myintArray is -1 and 420

    satan# rmmod hello-5
    Goodbye, world 5

    satan# insmod hello-5.o mystring="supercalifragilisticexpialidocious" \
    > mybyte=256 myintArray=-1,-1
    mybyte is an 8 bit integer: 0
    myshort is a short integer: 1
    myint is an integer: 20
    mylong is a long integer: 9999
    mystring is a string: supercalifragilisticexpialidocious
    myintArray is -1 and -1

    satan# rmmod hello-5
    Goodbye, world 5

    satan# insmod hello-5.o mylong=hello
    hello-5.o: invalid argument syntax for mylong: 'h'
    Óɶà¸öÎļþ¹¹³ÉµÄÄÚºËÄ£¿é
    ÓÐʱ½«Ä£¿éµÄÔ´´úÂë·ÖΪ¼¸¸öÎļþÊÇÒ»¸öÃ÷ÖǵÄÑ¡Ôñ¡£ÔÚÕâÖÖÇé¿öÏ£¬ÄãÐèÒª£º


    Ö»ÒªÔÚÒ»¸öÔ´ÎļþÖÐÌí¼Ó#define __NO_VERSION__Ô¤´¦ÀíÃüÁî¡£ ÕâºÜÖØÒªÒòΪmodule.hͨ³£°üº¬ kernel_versionµÄ¶¨Ò壬´Ëʱһ¸ö´æ´¢×ÅÄں˰汾µÄÈ«¾Ö±äÁ¿½«»á±»±àÒë¡£µ«Èç¹û´ËʱÄãÓÖÒª°üº¬Í·Îļþ version.h£¬Äã±ØÐëÊÖ¶¯°üº¬Ëü£¬ÒòΪ module.h²»»áÔÙ°üº¬ËüÈç¹û´ò¿ªÔ¤´¦ÀíÑ¡Ïî__NO_VERSION__¡£

    Ïñͨ³£Ò»Ñù±àÒë¡£

    ½«ËùÓеÄÄ¿±êÎļþÁ¬½ÓΪһ¸öÎļþ¡£ÔÚx86ƽ̨Ï£¬Ê¹ÓÃÃüÁîld -m elf_i386 -r -o <1st src file.o> <2nd src file.o>¡£

    ´ËʱMakefileÒ»Èç¼ÈÍù»á°ïÎÒÃÇÍê³É±àÒëºÍÁ¬½ÓµÄÔà»î¡£

    ÕâÀïÊÇÕâÑùµÄÒ»¸öÄ£¿é·¶Àý¡£

    Example 2-8. start.c

    /*
    * start.c - Illustration of multi filed modules
    */

    #include /* We're doing kernel work */
    #include /* Specifically, a module */

    int init_module(void)
    {
    printk("Hello, world - this is the kernel speaking\n" );
    return 0;
    }
    ÁíÒ»¸öÎļþ£º

    Example 2-9. stop.c

    /*
    * stop.c - Illustration of multi filed modules
    */

    #include /* We're doing kernel work */
    #include /* Specifically, a module */

    void cleanup_module()
    {
    printk("<1>Short is the life of a kernel module\n" );
    }
    ×îºóÊǸÃÄ£¿éµÄMakefile£º

    Example 2-10. Makefile

    obj-m += hello-1.o
    obj-m += hello-2.o
    obj-m += hello-3.o
    obj-m += hello-4.o
    obj-m += hello-5.o
    obj-m += startstop.o
    startstop-objs := start.o stop.o
    ΪÒѱàÒëµÄÄں˱àÒëÄ£¿é
    ºÜÏÔÈ»£¬ÎÒÃÇÇ¿ÁÒÍƼöÄã±àÒëÒ»¸öеÄÄںˣ¬ÕâÑùÄã¾Í¿ÉÒÔ´ò¿ªÄÚºËÖÐһЩÓÐÓõÄÅÅ´í¹¦ÄÜ£¬ÏñÇ¿ÖÆжÔØÄ£¿é(MODULE_FORCE_UNLOAD)£º µ±¸ÃÑ¡Ïî±»´ò¿ªÊ±£¬Äã¿ÉÒÔrmmod -f moduleÇ¿ÖÆÄÚºËжÔØÒ»¸öÄ£¿é£¬¼´Ê¹ÄÚºËÈÏΪÕâÊDz»°²È«µÄ¡£¸ÃÑ¡Ïî¿ÉÒÔΪÄã½ÚÊ¡²»ÉÙ¿ª·¢Ê±¼ä¡£

    µ«ÊÇ£¬ÄãÈÔÈ»ÓÐÐí¶àʹÓÃÒ»¸öÕýÔÚÔËÐÐÖеÄÒѱàÒëµÄÄں˵ÄÀíÓÉ¡£ÀýÈ磬ÄãûÓбàÒëºÍ°²×°ÐÂÄں˵ÄȨÏÞ£¬»òÕßÄ㲻ϣÍûÖØÆôÄãµÄ»úÆ÷À´ÔËÐÐÐÂÄںˡ£ Èç¹ûÄã¿ÉÒÔºÁÎÞ×è°­µÄ±àÒëºÍʹÓÃÒ»¸öеÄÄںˣ¬Äã¿ÉÒÔÌø¹ýʣϵÄÄÚÈÝ£¬È¨µ±ÊÇÒ»¸ö½Å×¢¡£

    Èç¹ûÄã½ö½öÊÇ°²×°ÁËÒ»¸öеÄÄں˴úÂëÊ÷²¢ÓÃËüÀ´±àÒëÄãµÄÄ£¿é£¬µ±Äã¼ÓÔØÄãµÄÄ£¿éʱ£¬ÄãºÜ¿ÉÄÜ»áµÃµ½ÏÂÃæµÄ´íÎóÌáʾ£º

    insmod: error inserting 'poet_atkm.ko': -1 Invalid module format

    һЩ²»ÄÇôÉñÃصÄÐÅÏ¢±»¼Í¼ÔÚÎļþ/var/log/messagesÖУ»

    Jun 4 22:07:54 localhost kernel: poet_atkm: version magic '2.6.5-1.358custom 686
    REGPARM 4KSTACKS gcc-3.3' should be '2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3'

    »»¾ä»°Ëµ£¬Äں˾ܾø¼ÓÔØÄãµÄÄ£¿éÒòΪ¼ÇÔØ°æ±¾ºÅµÄ×Ö·û´®²»·û(¸üÈ·ÇеÄ˵ÊÇ°æ±¾Ó¡´Á)¡£°æ±¾Ó¡´Á×÷Ϊһ¸ö¾²Ì¬µÄ×Ö·û´®´æÔÚÓÚÄÚºËÄ£¿éÖУ¬ÒÔ vermagic:¡£ °æ±¾ÐÅÏ¢ÊÇÔÚÁ¬½Ó½×¶Î´ÓÎļþinit/vermagic.oÖлñµÃµÄ¡£ ²é¿´°æ±¾Ó¡´ÁºÍÆäËüÔÚÄ£¿éÖеÄһЩ×Ö·ûÐÅÏ¢£¬¿ÉÒÔʹÓÃÏÂÃæµÄÃüÁî modinfo module.ko£º

    [root@pcsenonsrv 02-HelloWorld]# modinfo hello-4.ko
    license: GPL
    author: Peter Jay Salzman <p@dirac.org>
    description: A sample driver
    vermagic: 2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3
    depends:

    ÎÒÃÇ¿ÉÒÔ½èÖúÑ¡Ïî--force-vermagic½â¾ö¸ÃÎÊÌ⣬µ«ÕâÖÖ·½·¨ÓÐDZÔÚµÄΣÏÕ£¬ËùÒÔÔÚ³ÉÊìµÄÄ£¿éÖÐÒ²ÊDz»¿É½ÓÊܵġ£ ½â¾ö·½·¨ÊÇÎÒÃǹ¹½¨Ò»¸öͬÎÒÃÇÔ¤ÏȱàÒëºÃµÄÄÚºËÍêÈ«ÏàͬµÄ±àÒë»·¾³¡£ÈçºÎ¾ßÌåʵÏÖ½«ÊǸÃÕºóÃæµÄÄÚÈÝ¡£

    Ê×ÏÈ£¬×¼±¸Í¬ÄãÄ¿Ç°µÄÄں˰汾ÍêÈ«Ò»ÖµÄÄں˴úÂëÊ÷¡£È»ºó£¬ÕÒµ½ÄãµÄµ±Ç°Äں˵ıàÒëÅäÖÃÎļþ¡£Í¨³£Ëü¿ÉÒÔÔÚ·¾¶ /bootÏÂÕÒµ½£¬Ê¹ÓÃÏñconfig-2.6.xµÄÎļþÃû¡£Äã¿ÉÒÔÖ±½Ó½«Ëü¿½±´µ½Äں˴úÂëÊ÷µÄ·¾¶Ï£º cp /boot/config-`uname -r` /usr/src/linux-`uname -r`/.config¡£

    ÈÃÎÒÃÇÔÙ´Î×¢ÒâÒ»ÏÂÏÈÇ°µÄ´íÎóÐÅÏ¢£º×Ðϸ¿´µÄ»°Äã»á·¢ÏÖ£¬¼´Ê¹Ê¹ÓÃÍêÈ«ÏàͬµÄÅäÖÃÎļþ£¬°æ±¾Ó¡´Á»¹ÊÇÓÐϸСµÄ²îÒìµÄ£¬µ«Õâ×ãÒÔµ¼Ö ģ¿é¼ÓÔصÄʧ°Ü¡£ÕâÆäÖеIJîÒì¾ÍÊÇÔÚÄ£¿éÖгöÏÖÈ´²»ÔÚÄÚºËÖгöÏÖµÄcustom×Ö·û´®£¬ÊÇÓÉijЩ·¢ÐаæÌṩµÄÐ޸ĹýµÄ makefileµ¼Öµġ£¼ì²é/usr/src/linux/Makefile£¬È·±£ÏÂÃæÕâЩÌض¨µÄ°æ±¾ÐÅϢͬÄãʹÓõÄÄÚºËÍêÈ«Ò»Ö£º

    VERSION = 2
    PATCHLEVEL = 6
    SUBLEVEL = 5
    EXTRAVERSION = -1.358custom
    ...

    ÏñÉÏÃæµÄÇé¿öÄã¾ÍÐèÒª½«EXTRAVERSIONÒ»Ïî¸ÄΪ-1.358¡£ÎÒÃǵĽ¨ÒéÊǽ«Ô­Ê¼µÄmakefile±¸·ÝÔÚ /lib/modules/2.6.5-1.358/buildÏ¡£ Ò»¸ö¼òµ¥µÄÃüÁîcp /lib/modules/`uname -r`/build/Makefile /usr/src/linux-`uname -r`¼´¿É¡£ ÁíÍ⣬Èç¹ûÄãÒѾ­ÔÚÔËÐÐÒ»¸öÓÉÉÏÃæµÄ´íÎóµÄMakefile±àÒëµÄÄںˣ¬ÄãÓ¦¸ÃÖØÐÂÖ´ÐÐ make£¬»òÖ±½Ó¶ÔÓ¦/lib/modules/2.6.x/build/include/linux/version.h´ÓÎļþ /usr/src/linux-2.6.x/include/linux/version.hÐÞ¸ÄUTS_RELEASE£¬»òÓÃÇ°Õ߸²¸ÇºóÕߵġ£

    ÏÖÔÚ£¬ÇëÖ´ÐÐmakeÀ´¸üÐÂÉèÖúͰ汾Ïà¹ØµÄÍ·Îļþ£¬Ä¿±êÎļþ£º

    [root@pcsenonsrv linux-2.6.x]# make
    CHK include/linux/version.h
    UPD include/linux/version.h
    SYMLINK include/asm -> include/asm-i386
    SPLIT include/linux/autoconf.h -> include/config/*
    HOSTCC scripts/basic/fixdep
    HOSTCC scripts/basic/split-include
    HOSTCC scripts/basic/docproc
    HOSTCC scripts/conmakehash
    HOSTCC scripts/kallsyms
    CC scripts/empty.o
    ...

    Èç¹ûÄã²»ÊÇȷʵÏë±àÒëÒ»¸öÄںˣ¬Äã¿ÉÒÔÔÚSPLITºóͨ¹ý°´ÏÂCTRL-CÖÐÖ¹±àÒë¹ý³Ì¡£ÒòΪ´ËʱÄãÐèÒªµÄÎļþ ÒѾ­¾ÍÐ÷ÁË¡£ÏÖÔÚÄã¿ÉÒÔ·µ»ØÄãµÄÄ£¿éĿ¼Ȼºó±àÒë¼ÓÔØËü£º´Ëʱģ¿é½«ÍêÈ«Õë¶ÔÄãµÄµ±Ç°Äں˱àÒ룬¼ÓÔØʱҲ²»»áÓÉÈκδíÎóÌáʾ¡£