uclinux内核的console(5):printk相关的内核参数

快乐虾

http://blog.csdn.net/lights_joy/

[email protected]

本文适用于

ADI bf561 DSP

优视BF561EVB开发板

uclinux-2008r1.5-rc3 (smp patch)

Visual DSP++ 5.0 (update 5)

欢迎转载,但请保留作者信息

细看printk.c文件,可以发现几个与printk函数相关的参数:

1.1 log_buf_len

__setup("log_buf_len=", log_buf_len_setup);

即这个内核参数由log_buf_len_setup函数进行处理:

static char __log_buf[__LOG_BUF_LEN];

static char *log_buf = __log_buf;

static int log_buf_len = __LOG_BUF_LEN;

static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */

static int __init log_buf_len_setup(char *str)

{

unsigned long size = memparse(str, &str);

unsigned long flags;

if (size)

size = roundup_pow_of_two(size);

if (size > log_buf_len) {

unsigned long start, dest_idx, offset;

char *new_log_buf;

new_log_buf = alloc_bootmem(size);

if (!new_log_buf) {

printk(KERN_WARNING "log_buf_len: allocation failed\n");

goto out;

}

spin_lock_irqsave(&logbuf_lock, flags);

log_buf_len = size;

log_buf = new_log_buf;

offset = start = min(con_start, log_start);

dest_idx = 0;

while (start != log_end) {

log_buf[dest_idx] = __log_buf[start & (__LOG_BUF_LEN - 1)];

start++;

dest_idx++;

}

log_start -= offset;

con_start -= offset;

log_end -= offset;

spin_unlock_irqrestore(&logbuf_lock, flags);

printk(KERN_NOTICE "log_buf_len: %d\n", log_buf_len);

}

out:

return 1;

}

在默认情况下,printk缓冲区的大小由__LOG_BUF_LEN指定

#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)

#define CONFIG_LOG_BUF_SHIFT 14

214次方。输入的值必须比这个值大才有效果。而且由于使用了memparse进行数值的分析,因此它可以K, M, G这三个值。如:

log_buf_len=64k

1.2 ignore_loglevel

static int __read_mostly ignore_loglevel;

static int __init ignore_loglevel_setup(char *str)

{

ignore_loglevel = 1;

printk(KERN_INFO "debug: ignoring loglevel setting.\n");

return 1;

}

__setup("ignore_loglevel", ignore_loglevel_setup);

这个内核参数不需要设置值。这个参数仅用在_call_console_drivers函数中

static void _call_console_drivers(unsigned long start,

unsigned long end, int msg_log_level)

{

if ((msg_log_level < console_loglevel || ignore_loglevel) &&

console_drivers && start != end) {

if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {

/* wrapped write */

__call_console_drivers(start & LOG_BUF_MASK,

log_buf_len);

__call_console_drivers(0, end & LOG_BUF_MASK);

} else {

__call_console_drivers(start, end);

}

}

}

在使用了这个内核参数后,printk将忽略输出的级别,直接将传递进来的所有信息输出。

1.3 KERN_*

在使用printk输出的时候,可以使用KERN_*宏来指定输出级别。

#define KERN_EMERG "<0>" /* system is unusable */

#define KERN_ALERT "<1>" /* action must be taken immediately */

#define KERN_CRIT "<2>" /* critical conditions */

#define KERN_ERR "<3>" /* error conditions */

#define KERN_WARNING "<4>" /* warning conditions */

#define KERN_NOTICE "<5>" /* normal but significant condition */

#define KERN_INFO "<6>" /* informational */

#define KERN_DEBUG "<7>" /* debug-level messages */

_call_console_drivers函数中可以看到,当指定的输出级别大于等于console_loglevel时,信息将不会输出。console_loglevel的定义为:

#define console_loglevel (console_printk[0])

当使用printk而不指定输出级别时,printk取默认级别default_message_loglevel,其定义为:

#define default_message_loglevel (console_printk[1])

这里涉及的console_printk是一个全局变量:

int console_printk[4] = {

DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */

DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */

MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */

DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */

};

#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */

#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */

因此,只要不是在输出时指定KERN_DEBUG,其信息都将被printk输出。

1.4 printk_time

这个参数定义为:

#if defined(CONFIG_PRINTK_TIME)

static int printk_time = 1;

#else

static int printk_time = 0;

#endif

module_param(printk_time, int, S_IRUGO | S_IWUSR);

static int __init printk_time_setup(char *str)

{

if (*str)

return 0;

printk_time = 1;

return 1;

}

__setup("time", printk_time_setup);

在指定这个参数之后,printk将在每条信息之前加上时间。

asmlinkage int vprintk(const char *fmt, va_list args)

{

…………………………….

for (p = printk_buf; *p; p++) {

if (log_level_unknown) {

/* log_level_unknown signals the start of a new line */

if (printk_time) {

int loglev_char;

char tbuf[50], *tp;

unsigned tlen;

unsigned long long t;

unsigned long nanosec_rem;

/*

* force the log level token to be

* before the time output.

*/

if (p[0] == '<' && p[1] >='0' &&

p[1] <= '7' && p[2] == '>') {

loglev_char = p[1];

p += 3;

printed_len -= 3;

} else {

loglev_char = default_message_loglevel

+ '0';

}

t = printk_clock();

nanosec_rem = do_div(t, 1000000000);

tlen = sprintf(tbuf,

"<%c>[%5lu.%06lu] ",

loglev_char,

(unsigned long)t,

nanosec_rem/1000);

for (tp = tbuf; tp < tbuf + tlen; tp++)

emit_log_char(*tp);

printed_len += tlen;

} else {

if (p[0] != '<' || p[1] < '0' ||

p[1] > '7' || p[2] != '>') {

emit_log_char('<');

emit_log_char(default_message_loglevel

+ '0');

emit_log_char('>');

printed_len += 3;

}

}

log_level_unknown = 0;

if (!*p)

break;

}

emit_log_char(*p);

if (*p == '\n')

log_level_unknown = 1;

}

………………………

}

1 参考资料

uclinux内核的console(1):数据结构(2009-1-31)

uclinux内核的console(2)early console(2009-1-31)

uclinux内核的console(3)console驱动初始化(2009-1-31)

uclinux内核的console(4):通过console输出信息(2009-1-31)

你可能感兴趣的:(数据结构,.net,Blog)