三 printk如何打印信息

printk的定义

可变参数 参考va_list,va_start,va_arg,va_end可变参数

  1. asmlinkage int printk(const char *fmt, ...)  
  2. {  
  3.     va_list args;   //可变参数链表  
  4.     int r;  
  5.   
  6. #ifdef CONFIG_KGDB_KDB  
  7.     if (unlikely(kdb_trap_printk)) {  
  8.         va_start(args, fmt);  
  9.         r = vkdb_printf(fmt, args);  
  10.         va_end(args);  
  11.         return r;  
  12.     }  
  13. #endif  
  14.     va_start(args, fmt);    //获取第一个可变参数  
  15.     r = vprintk(fmt, args); //调用vprintk函数  
  16.     va_end(args);   //释放可变参数链表指针  
  17.   
  18.     return r;  
  19. }  

vprintk函数

  1. asmlinkage int vprintk(const char *fmt, va_list args)  
  2. {  
  3.     int printed_len = 0;  
  4.     int current_log_level = default_message_loglevel;  
  5.     unsigned long flags;  
  6.     int this_cpu;  
  7.     char *p;  
  8.   
  9.     boot_delay_msec();  
  10.     printk_delay();  
  11.     preempt_disable();  
  12.     raw_local_irq_save(flags);  
  13.     this_cpu = smp_processor_id();  
  14.     if (unlikely(printk_cpu == this_cpu)) {  
  15.         if (!oops_in_progress) {  
  16.             recursion_bug = 1;  
  17.             goto out_restore_irqs;  
  18.         }  
  19.         zap_locks();  
  20.     }  
  21.   
  22.     lockdep_off();  
  23.     spin_lock(&logbuf_lock);  
  24.     printk_cpu = this_cpu;  
  25.   
  26.     if (recursion_bug) {  
  27.         recursion_bug = 0;  
  28.         strcpy(printk_buf, recursion_bug_msg);  
  29.         printed_len = strlen(recursion_bug_msg);  
  30.     }  
  31.     printed_len += vscnprintf(printk_buf + printed_len,sizeof(printk_buf) - printed_len, fmt, args);  
  32.     p = printk_buf;  
  33.     if (p[0] == '<') {       //处理打印级别字段  
  34.         unsigned char c = p[1];  
  35.         if (c && p[2] == '>') {  
  36.             switch (c) {  
  37.             case '0' ... '7'/* loglevel */  
  38.                 current_log_level = c - '0';  
  39.             case 'd'/* KERN_DEFAULT */  
  40.                 if (!new_text_line) {  
  41.                     emit_log_char('\n');  
  42.                     new_text_line = 1;  
  43.                 }  
  44.             case 'c'/* KERN_CONT */  
  45.                 p += 3;  
  46.                 break;  
  47.             }  
  48.         }  
  49.     }  
  50.     for ( ; *p; p++) {  
  51.         if (new_text_line) {  
  52.             /* Always output the token */  
  53.             emit_log_char('<');  
  54.             emit_log_char(current_log_level + '0');  
  55.             emit_log_char('>');  
  56.             printed_len += 3;  
  57.             new_text_line = 0;  
  58.   
  59.             if (printk_time) {      //打印时间信息  
  60.                 /* Follow the token with the time */  
  61.                 char tbuf[50], *tp;  
  62.                 unsigned tlen;  
  63.                 unsigned long long t;  
  64.                 unsigned long nanosec_rem;  
  65.   
  66.                 t = cpu_clock(printk_cpu);  
  67.                 nanosec_rem = do_div(t, 1000000000);  
  68.                 tlen = sprintf(tbuf, "[%5lu.%06lu] ",(unsigned long) t,nanosec_rem / 1000);  
  69.   
  70.                 for (tp = tbuf; tp < tbuf + tlen; tp++)  
  71.                     emit_log_char(*tp);  
  72.                 printed_len += tlen;  
  73.             }  
  74.   
  75.             if (!*p)  
  76.                 break;  
  77.         }  
  78.   
  79.         emit_log_char(*p);  
  80.         if (*p == '\n')  
  81.             new_text_line = 1;  
  82.     }  
  83.     if (acquire_console_semaphore_for_printk(this_cpu))  
  84.         release_console_sem();  
  85.   
  86.     lockdep_on();  
  87. out_restore_irqs:  
  88.     raw_local_irq_restore(flags);  
  89.   
  90.     preempt_enable();  
  91.     return printed_len;  
  92. }  

接着调用release_console_sem函数

  1. void release_console_sem(void)  
  2. {  
  3.     unsigned long flags;  
  4.     unsigned _con_start, _log_end;  
  5.     unsigned wake_klogd = 0;  
  6.   
  7.     if (console_suspended) {  
  8.         up(&console_sem);  
  9.         return;  
  10.     }  
  11.   
  12.     console_may_schedule = 0;  
  13.   
  14.     for ( ; ; ) {  
  15.         spin_lock_irqsave(&logbuf_lock, flags);  
  16.         wake_klogd |= log_start - log_end;  
  17.         if (con_start == log_end)  
  18.             break;          /* Nothing to print */  
  19.         _con_start = con_start;  
  20.         _log_end = log_end;  
  21.         con_start = log_end;        /* Flush */  
  22.         spin_unlock(&logbuf_lock);  
  23.         stop_critical_timings();    /* don't trace print latency */  
  24.         call_console_drivers(_con_start, _log_end);  
  25.         start_critical_timings();  
  26.         local_irq_restore(flags);  
  27.     }  
  28.     console_locked = 0;  
  29.     up(&console_sem);  
  30.     spin_unlock_irqrestore(&logbuf_lock, flags);  
  31.     if (wake_klogd)  
  32.         wake_up_klogd();  
  33. }  
  34. EXPORT_SYMBOL(release_console_sem);  

调用call_console_drivers函数

  1. static void call_console_drivers(unsigned start, unsigned end)  
  2. {  
  3.     unsigned cur_index, start_print;  
  4.     static int msg_level = -1;  
  5.   
  6.     BUG_ON(((int)(start - end)) > 0);  
  7.   
  8.     cur_index = start;  
  9.     start_print = start;  
  10.     while (cur_index != end) {  
  11.         if (msg_level < 0 && ((end - cur_index) > 2) &&LOG_BUF(cur_index + 0) == '<' &&LOG_BUF(cur_index + 1) >= '0' &&LOG_BUF(cur_index + 1) <= '7' &&LOG_BUF(cur_index + 2) == '>') {  
  12.             msg_level = LOG_BUF(cur_index + 1) - '0';  
  13.             cur_index += 3;  
  14.             start_print = cur_index;  
  15.         }  
  16.         while (cur_index != end) {  
  17.             char c = LOG_BUF(cur_index);  
  18.   
  19.             cur_index++;  
  20.             if (c == '\n') {  
  21.                 if (msg_level < 0) {  
  22.                     msg_level = default_message_loglevel;  
  23.                 }  
  24.                 _call_console_drivers(start_print, cur_index, msg_level);  
  25.                 msg_level = -1;  
  26.                 start_print = cur_index;  
  27.                 break;  
  28.             }  
  29.         }  
  30.     }  
  31.     _call_console_drivers(start_print, end, msg_level);  
  32. }  

_call_console_drivers函数

  1. static void _call_console_drivers(unsigned start,unsigned end, int msg_log_level)  
  2. {  
  3.     if ((msg_log_level < console_loglevel || ignore_loglevel) && console_drivers && start != end) {  
  4.         if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {  
  5.             /* wrapped write */  
  6.             __call_console_drivers(start & LOG_BUF_MASK,log_buf_len);  
  7.             __call_console_drivers(0, end & LOG_BUF_MASK);  
  8.         } else {  
  9.             __call_console_drivers(start, end);  
  10.         }  
  11.     }  
  12. }  

__call_console_drivers函数

遍历console_drivers数组

  1. #define for_each_console(con) \  
  2.     for (con = console_drivers; con != NULL; con = con->next)  

调用console的写方法

  1. static void __call_console_drivers(unsigned start, unsigned end)  
  2. {  
  3.     struct console *con;  
  4.   
  5.     for_each_console(con) {  
  6.         if ((con->flags & CON_ENABLED) && con->write &&(cpu_online(smp_processor_id()) ||(con->flags & CON_ANYTIME)))  
  7.             con->write(con, &LOG_BUF(start), end - start);   //调用console的写方法  
  8.     }  
  9. }  
console_drivers链表在register_console中会设置
二 console 设备驱动
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值