DSP

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

2019-07-13 16:59发布

快乐虾 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)