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

本文详细解析了uCLinux内核中的printk机制,包括printk缓冲区大小配置、输出级别控制、时间戳添加等功能,并介绍了如何通过内核参数调整这些功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

快乐虾

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

lights@hb165.com

  

本文适用于

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)

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值