注意上面說到的是:“幾乎”在內核的任何地方都可以使用。那什麼地方使用會有“問題”?那就是在系統啓動過程的早期,終端初始化之前的某些地方雖然可以使用,但是在終端和控制檯被初始化之前所有信息都被緩存在printk的簡單的ring buffer(環形緩衝區)中,直到終端和控制檯被初始化之後,所有緩存信息都被一併輸出。
-
#define KERN_EMERG "<0>" /* 系統不可使用 */
-
#define KERN_ALERT "<1>" /* 需要立即採取行動 */
-
#define KERN_CRIT "<2>" /* 嚴重情況 */
-
#define KERN_ERR "<3>" /* 錯誤情況 */
-
#define KERN_WARNING "<4>" /* 警告情況 */
-
#define KERN_NOTICE "<5>" /* 正常情況, 但是值得注意 */
-
#define KERN_INFO "<6>" /* 信息型消息 */
-
#define KERN_DEBUG "<7>" /* 調試級別的信息 */
-
-
/* 使用默認內核日誌級別 */
-
#define KERN_DEFAULT "<d>"
-
/*
-
* 標註爲一個“連續”的日誌打印輸出行(只能用於一個
-
* 沒有用 \n封閉的行之後). 只能用於啓動初期的
core/arch 代碼
-
* (否則續行是非SMP的安全).
-
*/
- #define KERN_CONT "<c>"
-
/* printk's without
a loglevel use this.. */
- #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
- printk(KERN_EMERG "log_level:%s\n", KERN_EMERG);
- printk( "<0>" "log_level:%s\n", KERN_EMERG);
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <errno.h>
-
//#define __LIBRARY__ /* _syscall3 and friends
are only available through this */
-
//#include <linux/unistd.h>
-
/* define the system call, to override
the library function */
-
//_syscall3(int, syslog, int, type, char *, bufp, int, len);
-
-
int main(int argc, char **argv)
-
{
-
int level;
-
if (argc == 2) {
-
level = atoi(argv[1]); /* the
chosen console */
-
} else {
-
fprintf(stderr, "%s:
need a single arg\n", argv[0]);
-
exit(1);
-
}
-
if (klogctl(8, NULL, level) < 0) {
-
fprintf(stderr, "%s:
syslog(setlevel): %s\n",
-
argv[0], strerror(errno));
-
exit(1);
-
}
-
exit(0);
- }
-
#ifndef pr_fmt
-
#define pr_fmt(fmt) fmt
-
#endif
-
-
#define pr_emerg(fmt, ...) \
-
printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
-
#define pr_alert(fmt, ...) \
-
printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
-
#define pr_crit(fmt, ...) \
-
printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
-
#define pr_err(fmt, ...) \
-
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
-
#define pr_warning(fmt, ...) \
-
printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
-
#define pr_warn pr_warning
-
#define pr_notice(fmt, ...) \
-
printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
-
#define pr_info(fmt, ...) \
-
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
-
#define pr_cont(fmt, ...) \
-
printk(KERN_CONT fmt, ##__VA_ARGS__)
-
-
/* 除非定義了DEBUG ,否則pr_devel()不產生任何代碼 */
-
#ifdef DEBUG
-
#define pr_devel(fmt, ...) \
-
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-
#else
-
#define pr_devel(fmt, ...) \
-
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-
#endif
-
-
/* 如果你在寫一個驅動,請使用dev_dbg */
-
#if defined(DEBUG)
-
#define pr_debug(fmt, ...) \
-
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-
#elif defined(CONFIG_DYNAMIC_DEBUG)
-
/* dynamic_pr_debug() uses
pr_fmt() internally so we don't need it here */
-
#define pr_debug(fmt, ...) \
-
dynamic_pr_debug(fmt, ##__VA_ARGS__)
-
#else
-
#define pr_debug(fmt, ...) \
-
no_printk(KERN_DEBUG
pr_fmt(fmt), ##__VA_ARGS__)
- #endif
在調試的時候,有時某些部分可能printk會產生大量輸出, 導致系統無法正常工作,並可能使系統日誌ring buffer溢出(舊的信息被快速覆蓋)。特別地,當使用一個慢速控制檯設備(如串口), 過量輸出也能拖慢系統。這樣反而難於發現系統出問題的地方。所以你應當非常注意:正常操作時不應當打印任何東西,打印的輸出應當是指示需要注意的異常,並小心不要做過頭。
- #define printk_ratelimit() __printk_ratelimit(__func__)
這個函數應當在你認爲打印一個可能會出現大量重複的消息之前調用,如果這個函數返回非零值, 繼續打印你的消息, 否則跳過它。典型的調用如這樣:
-
if (printk_ratelimit())
- printk(KERN_NOTICE "The printer is still on fire\n");
- /proc/sys/kern/printk_ratelimit( 可以看作一個監測週期,在這個週期內只能發出下面的控制量的信息)
- /proc/sys/kernel/printk_ratelimit_burst(以上週期內的最大消息數,如果超過了printk_ratelimit()返回0)
- static char __log_buf[__LOG_BUF_LEN];
-
/*
-
* 在指向log_buf時並沒有用log_buf_len做限制 - 所以他們
- * 在作爲下標使用前必須用掩碼處理(去除CONFIG_LOG_BUF_SHIFT以上的高位)
-
*/
-
static unsigned log_start; /* log_buf中的索引: 指向由syslog()讀取的下一個字符 */
-
static unsigned con_start; /* log_buf中的索引: 指向發送到console的下一個字符 */
- static unsigned log_end; /* log_buf中的索引:最近寫入的字符地址 + 1 */