[知其然不知其所以然-23] Something about the printk loglevel and var_list

来源:互联网 发布:sql分组查询 编辑:程序博客网 时间:2024/05/09 10:28
int console_printk[4] = {CONSOLE_LOGLEVEL_DEFAULT,/* console_loglevel */MESSAGE_LOGLEVEL_DEFAULT,/* default_message_loglevel */CONSOLE_LOGLEVEL_MIN,/* minimum_console_loglevel */CONSOLE_LOGLEVEL_DEFAULT,/* default_console_loglevel */};


#define console_loglevel (console_printk[0])#define default_message_loglevel (console_printk[1])#define minimum_console_loglevel (console_printk[2])#define default_console_loglevel (console_printk[3])

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

So the initial value of console_loglevel is 7, thus in 

static void call_console_drivers(int level, const char *ext_text, size_t ext_len, const char *text, size_t len){struct console *con;if (level >= console_loglevel && !ignore_loglevel)return;
For any printk(KERN_LEVEL string) , if KERN_LEVEL < 7, the message will be printed to consoles.

For example printk(KERN_INFO string) will print the message to console.

#define KERN_EMERGKERN_SOH "0"/* system is unusable */#define KERN_ALERTKERN_SOH "1"/* action must be taken immediately */#define KERN_CRITKERN_SOH "2"/* critical conditions */#define KERN_ERRKERN_SOH "3"/* error conditions */#define KERN_WARNINGKERN_SOH "4"/* warning conditions */#define KERN_NOTICEKERN_SOH "5"/* normal but significant condition */#define KERN_INFOKERN_SOH "6"/* informational */#define KERN_DEBUGKERN_SOH "7"/* debug-level messages */


Meanwhile there is also no KERN_LEVEL provided, thus printk(string), so what's the behavior for

this situation? It is implemented in vprintk_emit:

level = LOGLEVEL_DEFAULT = -1;/* * For default printk(string), the level returned by printk_get_level * is 0, for printk(KERN_INFO, string), level is KERN_INFO - '0' */level = printk_get_level(text);if (level == LOGLEVEL_DEFAULT)level = default_message_loglevel;
From above code, default_message_loglevel is MESSAGE_LOGLEVEL_DEFAULT,

which is set by kernel config:

#define MESSAGE_LOGLEVEL_DEFAULT CONFIG_MESSAGE_LOGLEVEL_DEFAULT

normally we have:

MESSAGE_LOGLEVEL_DEFAULT [=4] 
which means that, the default printk level is KERN_WARNING.

After studying the loglevel, I'd like to introduce the va_list, let's take printk for example:

asmlinkage int printk_emit(int facility, int level,   const char *dict, size_t dictlen,   const char *fmt, ...){va_list args;int r;va_start(args, fmt);r = vprintk_emit(facility, level, dict, dictlen, fmt, args);va_end(args);return r;}

First we see, the last fixed know param is 

const char *fmt, thus the format field, then we

have '...' symbol, which means the following params

are variable in number, for example:

printk("%s"%d%u", param1, param2, param3...) 

the param1~3 is repesented by '...', and "%s%d%u" is

just the const char *fmt, and most important thing is,

the params are pushed on a stack, from right to left,

thus first push param 3, then param 2, then param 1, and

finally push const char *fmt, since most stacks are growed

from top to down, the address of fmt is smallest, then we

can add offset to &fmt, then get the rest address of variable params.

In our case, va_start(args, fmt) is to store the first address behind fmt

to args, then:

vscnprintf(text, sizeof(textbuf), fmt, args);
to analysis the variable params, and format them according to args, and 

finally put them into a new string buf named text, from then on,  check

the content of buf text, to decide the loglevel in the front of text, for example,

if started with KERN_SOH, which is "\001", then we know we need to

check the following loglevel.


0 0