printk函数
Weusedtheprintkfunctioninearlierchapterswiththesimplifyingassumptionthatitworkslikeprintf.Nowit'stimetointroducesomeofthedifferences.
我们在前面章节中简单地把 printk 当作 printf 函数来使用。现在是时候来介绍它的一些不同之处了。
Oneofthedifferencesisthatprintkletsyouclassifymessagesaccordingtotheirseveritybyassociatingdifferentloglevels,orpriorities,withthemessages.Youusuallyindicatetheloglevelwithamacro.Forexample,KERN_INFO,whichwesawprependedtosomeoftheearlierprintstatements,isoneofthepossibleloglevelsofthemessage.Theloglevelmacroexpandstoastring,whichisconcatenatedtothemessagetextatcompiletime;that'swhythereisnocommabetweenthepriorityandtheformatstringinthefollowingexamples.Herearetwoexamplesofprintkcommands,adebugmessageandacriticalmessage:
其中一个不同点是,printk 允许你按照相关的记录级或优先级将消息严格分类。通常你需要一个宏来指定 记录等级。例如,KERN_INFO,我们在早先的的例子中看到过这个宏,它就是消息 记录等级的一种。 记录等级宏的作用是扩展为一个字符串,这个字符串会在编译期间与相应的消息文本相连接;这就解释了下面例子中为什么在优先级和格式化字符串之间没有逗号了。下面是两个printk函数的例子,一个是调试 消息,一个是临界 消息:
Thereareeightpossibleloglevelstrings,definedintheheader <linux></linux><linux></linux> ;welisttheminorderofdecreasingseverity:
在头文件 <linux/kernel.h> 中共定义了八个可用的记录级;我们下面按其严重性倒序列出:
KERN_EMERG
Usedforemergencymessages,usuallythosethatprecedeacrash.
用于 突发性事件的消息,通常在系统崩溃之前报告此类消息。
KERN_ALERT
Asituationrequiringimmediateaction.
在需要立即操作的情况下使用此消息。
KERN_CRIT
Criticalconditions,oftenrelatedtoserioushardwareorsoftwarefailures.
用于临界条件下,通常遇到严重的硬软件错误时使用此消息。
KERN_ERR
Usedtoreporterrorconditions;devicedriversoftenuseKERN_ERRtoreporthardwaredifficulties.
用于报告错误条件;设备驱动经常使用KERN_ERR报告硬件难题。
KERN_WARNING
Warningsaboutproblematicsituationsthatdonot,inthemselves,createseriousproblemswiththesystem.
是关于问题状况的警告,一般这些状况不会引起系统的严重问题。
KERN_NOTICE
Situationsthatarenormal,butstillworthyofnote.Anumberofsecurity-relatedconditionsarereportedatthislevel.
该级别较为普通,但仍然值得注意。许多与安全性相关的情况会在这个级别被报告。
KERN_INFO
Informationalmessages.Manydriversprintinformationaboutthehardwaretheyfindatstartuptimeatthislevel.
信息消息。许多驱动程序在启动时刻用它来输出获得的硬件信息。
KERN_DEBUG
Usedfordebuggingmessages.
用于输出调试信息
Eachstring(inthemacroexpansion)representsanintegerinanglebrackets.Integersrangefrom0to7,withsmallervaluesrepresentinghigherpriorities.
每一个字符串( 由宏扩展而成)表示了尖括号内的一个整数。 数值范围从0到7, 数值越小,优先级越高。
AprintkstatementwithnospecifiedprioritydefaultstoDEFAULT_MESSAGE_LOGLEVEL,specifiedinkernel/printk.casaninteger.Inthe2.6.10kernel,DEFAULT_MESSAGE_LOGLEVELisKERN_WARNING,butthathasbeenknowntochangeinthepast.
一个printk的缺省优先级是DEFAULT_MESSAGE_LOGLEVEL,它是一个在kernel/printk.c文件中指定的整数。在2.6.10内核中,DEFAULT_MESSAGE_LOGLEVEL相当于KERN_WARNING,但 据说在 早期版本中这是两个不同的优先级。
Basedontheloglevel,thekernelmayprintthemessagetothecurrentconsole,beitatext-modeterminal,aserialport,oraparallelprinter.Ifthepriorityislessthantheintegervariableconsole_loglevel,themessageisdeliveredtotheconsoleonelineatatime(nothingissentunlessatrailingnewlineisprovided).Ifbothklogdandsyslogdarerunningonthesystem,kernelmessagesareappendedto/var/log/messages(orotherwisetreateddependingonyoursyslogdconfiguration),independentofconsole_loglevel.Ifklogdisnotrunning,themessagewon'treachuserspaceunlessyouread/proc/kmsg(whichisoftenmosteasilydonewiththedmesgcommand).Whenusingklogd,youshouldrememberthatitdoesn'tsaveconsecutiveidenticallines;itonlysavesthefirstsuchlineand,atalatertime,thenumberofrepetitionsitreceived.
基于这些 记录级,内核可以把消息输出到当前的控制台,也可以是一个文本模式的终端,一个串口,或是一个并口打印机。如果优先级小于整形变量console_loglevel, 那么一次将会只发送一行消息到控制台中( 除非遇到一个换行符,否则将什么都不会发送)。如果系统中运行了klogd和syslogd进程,那么内核消息就会被完整地添加到/var/log/messages文件中(或者根据你的syslogd进程的配置状况进行发送) 而忽略 console_loglevel,如果klogd没有运行, 那么消息将不会到达用户空间,除非你对/proc/kmsg文件读取(实际上这项工作已被较早的dmesg命令完成)。当使用klogd时,你应该记住它不会 保留重复的消息行; 对于它接收到的重复消息,它只会保留第一条。
Thevariableconsole_loglevelisinitializedtoDEFAULT_CONSOLE_LOGLEVELandcanbemodifiedthroughthesys_syslogsystemcall.Onewaytochangeitisbyspecifyingthe-cswitchwheninvokingklogd,asspecifiedintheklogdmanpage.Notethattochangethecurrentvalue,youmustfirstkillklogdandthenrestartitwiththe-coption.Alternatively,youcanwriteaprogramtochangetheconsoleloglevel.You'llfindaversionofsuchaprograminmisc-progs/setlevel.cinthesourcefilesprovidedonO'Reilly'sFTPsite.Thenewlevelisspecifiedasanintegervaluebetween1and8,inclusive.Ifitissetto1,onlymessagesoflevel0(KERN_EMERG)reachtheconsole;ifitissetto8,allmessages,includingdebuggingones,aredisplayed.
被初始化为 DEFAULT_CONSOLE_LOGLEVEL 的 console_loglevel 变量可以通过 sys_syslog 系统调用修改。改变它内容的一个方法就是在调用klogd时使用-c选项,具体参考klogd的man帮助。请注意,为了改变当前的数值,你必须首先结束klogd进程,并且用-c选项重新启动它。 另一种方法是,你可以写一个应用程序来改变控制台的 记录等级。你 可以在O'Reilly的FTP站点提供的源代码文件中找到/misc-progs/setlevel.c文件,其中就有一个这样的程序。新 记录级为一个1到8的整数。如果设置为1, 那么只有优先级为 0(KERN_EMERG) 的消息才可以到达控制台;如果等级设置为8,那么包括调试信息在内的所有消息都会 被显示。
Itisalsopossibletoreadandmodifytheconsoleloglevelusingthetextfile/proc/sys/kernel/printk.Thefilehostsfourintegervalues:thecurrentloglevel,thedefaultlevelformessagesthatlackanexplicitloglevel,theminimumallowedloglevel,andtheboot-timedefaultloglevel.Writingasinglevaluetothisfilechangesthecurrentlogleveltothatvalue;thus,forexample,youcancauseallkernelmessagestoappearattheconsolebysimplyentering:
也可以 通过文本文件/proc/sys/kernel/printk来获取和更改控制台的 记录等级。这个文件中存储着四个 整型数值: 当前记录级,缺省记录级,最低记录级和启动时刻的缺省 记录级。 可以向该文件写入一个单一数值来改变当前记录级;例如,如果你可以想所有的内核消息都可以在控制台中显示,可以使用以下命令:
#echo8>/proc/sys/kernel/printk
Itshouldnowbeapparentwhythehello.csamplehadtheKERN_ALERT;markers;theyaretheretomakesurethatthemessagesappearontheconsole.
现在你应该明白在 hello.c 示例代码中为什么会有 KERN_ALERT; 标识了吧;这样做可以保证消息顺利地输出到控制台中
Weusedtheprintkfunctioninearlierchapterswiththesimplifyingassumptionthatitworkslikeprintf.Nowit'stimetointroducesomeofthedifferences.
我们在前面章节中简单地把 printk 当作 printf 函数来使用。现在是时候来介绍它的一些不同之处了。
Oneofthedifferencesisthatprintkletsyouclassifymessagesaccordingtotheirseveritybyassociatingdifferentloglevels,orpriorities,withthemessages.Youusuallyindicatetheloglevelwithamacro.Forexample,KERN_INFO,whichwesawprependedtosomeoftheearlierprintstatements,isoneofthepossibleloglevelsofthemessage.Theloglevelmacroexpandstoastring,whichisconcatenatedtothemessagetextatcompiletime;that'swhythereisnocommabetweenthepriorityandtheformatstringinthefollowingexamples.Herearetwoexamplesofprintkcommands,adebugmessageandacriticalmessage:
其中一个不同点是,printk 允许你按照相关的记录级或优先级将消息严格分类。通常你需要一个宏来指定 记录等级。例如,KERN_INFO,我们在早先的的例子中看到过这个宏,它就是消息 记录等级的一种。 记录等级宏的作用是扩展为一个字符串,这个字符串会在编译期间与相应的消息文本相连接;这就解释了下面例子中为什么在优先级和格式化字符串之间没有逗号了。下面是两个printk函数的例子,一个是调试 消息,一个是临界 消息:
printk(KERN_DEBUG"HereIam:%s:%i/n",__FILE__,__LINE__);
printk(KERN_CRIT"I'mtrashed;givingupon%p/n",ptr);
Thereareeightpossibleloglevelstrings,definedintheheader <linux></linux><linux></linux> ;welisttheminorderofdecreasingseverity:
在头文件 <linux/kernel.h> 中共定义了八个可用的记录级;我们下面按其严重性倒序列出:
KERN_EMERG
Usedforemergencymessages,usuallythosethatprecedeacrash.
用于 突发性事件的消息,通常在系统崩溃之前报告此类消息。
KERN_ALERT
Asituationrequiringimmediateaction.
在需要立即操作的情况下使用此消息。
KERN_CRIT
Criticalconditions,oftenrelatedtoserioushardwareorsoftwarefailures.
用于临界条件下,通常遇到严重的硬软件错误时使用此消息。
KERN_ERR
Usedtoreporterrorconditions;devicedriversoftenuseKERN_ERRtoreporthardwaredifficulties.
用于报告错误条件;设备驱动经常使用KERN_ERR报告硬件难题。
KERN_WARNING
Warningsaboutproblematicsituationsthatdonot,inthemselves,createseriousproblemswiththesystem.
是关于问题状况的警告,一般这些状况不会引起系统的严重问题。
KERN_NOTICE
Situationsthatarenormal,butstillworthyofnote.Anumberofsecurity-relatedconditionsarereportedatthislevel.
该级别较为普通,但仍然值得注意。许多与安全性相关的情况会在这个级别被报告。
KERN_INFO
Informationalmessages.Manydriversprintinformationaboutthehardwaretheyfindatstartuptimeatthislevel.
信息消息。许多驱动程序在启动时刻用它来输出获得的硬件信息。
KERN_DEBUG
Usedfordebuggingmessages.
用于输出调试信息
Eachstring(inthemacroexpansion)representsanintegerinanglebrackets.Integersrangefrom0to7,withsmallervaluesrepresentinghigherpriorities.
每一个字符串( 由宏扩展而成)表示了尖括号内的一个整数。 数值范围从0到7, 数值越小,优先级越高。
AprintkstatementwithnospecifiedprioritydefaultstoDEFAULT_MESSAGE_LOGLEVEL,specifiedinkernel/printk.casaninteger.Inthe2.6.10kernel,DEFAULT_MESSAGE_LOGLEVELisKERN_WARNING,butthathasbeenknowntochangeinthepast.
一个printk的缺省优先级是DEFAULT_MESSAGE_LOGLEVEL,它是一个在kernel/printk.c文件中指定的整数。在2.6.10内核中,DEFAULT_MESSAGE_LOGLEVEL相当于KERN_WARNING,但 据说在 早期版本中这是两个不同的优先级。
Basedontheloglevel,thekernelmayprintthemessagetothecurrentconsole,beitatext-modeterminal,aserialport,oraparallelprinter.Ifthepriorityislessthantheintegervariableconsole_loglevel,themessageisdeliveredtotheconsoleonelineatatime(nothingissentunlessatrailingnewlineisprovided).Ifbothklogdandsyslogdarerunningonthesystem,kernelmessagesareappendedto/var/log/messages(orotherwisetreateddependingonyoursyslogdconfiguration),independentofconsole_loglevel.Ifklogdisnotrunning,themessagewon'treachuserspaceunlessyouread/proc/kmsg(whichisoftenmosteasilydonewiththedmesgcommand).Whenusingklogd,youshouldrememberthatitdoesn'tsaveconsecutiveidenticallines;itonlysavesthefirstsuchlineand,atalatertime,thenumberofrepetitionsitreceived.
基于这些 记录级,内核可以把消息输出到当前的控制台,也可以是一个文本模式的终端,一个串口,或是一个并口打印机。如果优先级小于整形变量console_loglevel, 那么一次将会只发送一行消息到控制台中( 除非遇到一个换行符,否则将什么都不会发送)。如果系统中运行了klogd和syslogd进程,那么内核消息就会被完整地添加到/var/log/messages文件中(或者根据你的syslogd进程的配置状况进行发送) 而忽略 console_loglevel,如果klogd没有运行, 那么消息将不会到达用户空间,除非你对/proc/kmsg文件读取(实际上这项工作已被较早的dmesg命令完成)。当使用klogd时,你应该记住它不会 保留重复的消息行; 对于它接收到的重复消息,它只会保留第一条。
Thevariableconsole_loglevelisinitializedtoDEFAULT_CONSOLE_LOGLEVELandcanbemodifiedthroughthesys_syslogsystemcall.Onewaytochangeitisbyspecifyingthe-cswitchwheninvokingklogd,asspecifiedintheklogdmanpage.Notethattochangethecurrentvalue,youmustfirstkillklogdandthenrestartitwiththe-coption.Alternatively,youcanwriteaprogramtochangetheconsoleloglevel.You'llfindaversionofsuchaprograminmisc-progs/setlevel.cinthesourcefilesprovidedonO'Reilly'sFTPsite.Thenewlevelisspecifiedasanintegervaluebetween1and8,inclusive.Ifitissetto1,onlymessagesoflevel0(KERN_EMERG)reachtheconsole;ifitissetto8,allmessages,includingdebuggingones,aredisplayed.
被初始化为 DEFAULT_CONSOLE_LOGLEVEL 的 console_loglevel 变量可以通过 sys_syslog 系统调用修改。改变它内容的一个方法就是在调用klogd时使用-c选项,具体参考klogd的man帮助。请注意,为了改变当前的数值,你必须首先结束klogd进程,并且用-c选项重新启动它。 另一种方法是,你可以写一个应用程序来改变控制台的 记录等级。你 可以在O'Reilly的FTP站点提供的源代码文件中找到/misc-progs/setlevel.c文件,其中就有一个这样的程序。新 记录级为一个1到8的整数。如果设置为1, 那么只有优先级为 0(KERN_EMERG) 的消息才可以到达控制台;如果等级设置为8,那么包括调试信息在内的所有消息都会 被显示。
Itisalsopossibletoreadandmodifytheconsoleloglevelusingthetextfile/proc/sys/kernel/printk.Thefilehostsfourintegervalues:thecurrentloglevel,thedefaultlevelformessagesthatlackanexplicitloglevel,theminimumallowedloglevel,andtheboot-timedefaultloglevel.Writingasinglevaluetothisfilechangesthecurrentlogleveltothatvalue;thus,forexample,youcancauseallkernelmessagestoappearattheconsolebysimplyentering:
也可以 通过文本文件/proc/sys/kernel/printk来获取和更改控制台的 记录等级。这个文件中存储着四个 整型数值: 当前记录级,缺省记录级,最低记录级和启动时刻的缺省 记录级。 可以向该文件写入一个单一数值来改变当前记录级;例如,如果你可以想所有的内核消息都可以在控制台中显示,可以使用以下命令:
#echo8>/proc/sys/kernel/printk
Itshouldnowbeapparentwhythehello.csamplehadtheKERN_ALERT;markers;theyaretheretomakesurethatthemessagesappearontheconsole.
现在你应该明白在 hello.c 示例代码中为什么会有 KERN_ALERT; 标识了吧;这样做可以保证消息顺利地输出到控制台中