Linux内核中printf的实现(printk与vprintk)

来源:岁月联盟 编辑:exp 时间:2011-09-09

大家应该都在找printf的实现,其实linux内核中就有,我本来想查一下,既然linux覆盖了中断向量表,那么怎么输出文字?就查printk的代码,发现原来printk就是printf。代码在printk.c


01
#printk
02
asmlinkage int printk( const char *fmt, ...)
03
{
04
         va_list args;
05
         int r;
06
 
07
         va_start (args, fmt);
08
         r = vprintk(fmt, args);
09
         va_end (args);
10
 
11
         return r;
12
 
13
}

001
# vsprintk
002
asmlinkage int vprintk( const char *fmt, va_list args)
003
{
004
         int printed_len = 0;
005
         int current_log_level = default_message_loglevel;
006
         unsigned long flags;
007
         int this_cpu;
008
         char *p;
009
 
010
         boot_delay_msec();
011
 
012
         preempt_disable();
013
         /* This stops the holder of console_sem just where we want him */
014
         raw_local_irq_save(flags);
015
         this_cpu = smp_processor_id();
016
 
017
         /*
018
          * Ouch, printk recursed into itself!
019
          */
020
         if (unlikely(printk_cpu == this_cpu)) {
021
                 /*
022
                  * If a crash is occurring during printk() on this CPU,
023
                  * then try to get the crash message out but make sure
024
                  * we can't deadlock. Otherwise just return to avoid the
025
                  * recursion and return - but flag the recursion so that
026
                  * it can be printed at the next appropriate moment:
027
                  */
028
                 if (!oops_in_progress) {
029
                         recursion_bug = 1;
030
                         goto out_restore_irqs;
031
                 }
032
                 zap_locks();
033
         }
034
 
035
         lockdep_off();
036
         spin_lock(&logbuf_lock);
037
         printk_cpu = this_cpu;
038
 
039
         if (recursion_bug) {
040
                 recursion_bug = 0;
041
                 strcpy (printk_buf, recursion_bug_msg);
042
                 printed_len = sizeof (recursion_bug_msg);
043
         }
044
         /* Emit the output into the temporary buffer */
045
         printed_len += vscnprintf(printk_buf + printed_len,
046
                                   sizeof (printk_buf) - printed_len, fmt, args);
047
 
048
 
049
#ifdef  CONFIG_DEBUG_LL
050
         printascii(printk_buf);
051
#endif
052
 
053
         /*
054
          * Copy the output into log_buf.  If the caller didn't provide
055
          * appropriate log level tags, we insert them here
056
          */
057
         for (p = printk_buf; *p; p++) {
058
                 if (new_text_line) {
059
                         /* If a token, set current_log_level and skip over */
060
                         if (p[0] == '<' && p[1] >= '0' && p[1] <= '7' &&
061
                             p[2] == '>' ) {
062
                                 current_log_level = p[1] - '0' ;
063
                                 p += 3;
064
                                 printed_len -= 3;
065
                         }
066
 
067
                         /* Always output the token */
068
                         emit_log_char( '<' );
069
                         emit_log_char(current_log_level + '0' );
070
                         emit_log_char( '>' );
071
                         printed_len += 3;
072
                         new_text_line = 0;
073
 
074
                         if (printk_time) {
075
                                 /* Follow the token with the time */
076
                                 char tbuf[50], *tp;
077
                                 unsigned tlen;
078
                                 unsigned long long t;
079
                                 unsigned long nanosec_rem;
080
 
081
                                 t = cpu_clock(printk_cpu);
082
                                 nanosec_rem = do_div(t, 1000000000);
083
                                 tlen = sprintf (tbuf, "[%5lu.%06lu] " ,
084
                                                 (unsigned long ) t,
085
                                                 nanosec_rem / 1000);
086
 
087
                                 for (tp = tbuf; tp < tbuf + tlen; tp++)
088
                                         emit_log_char(*tp);
089
                                 printed_len += tlen;
090
                         }
091
 
092
                         if (!*p)
093
                                 break ;
094
                 }
095
 
096
                 emit_log_char(*p);
097
                 if (*p == '/n' )
098
                         new_text_line = 1;
099
         }
100
 
101
         /*
102
          * Try to acquire and then immediately release the
103
          * console semaphore. The release will do all the
104
          * actual magic (print out buffers, wake up klogd,
105
          * etc).
106
          *
107
          * The acquire_console_semaphore_for_printk() function
108
          * will release 'logbuf_lock' regardless of whether it
109
          * actually gets the semaphore or not.
110
          */
111
         if (acquire_console_semaphore_for_printk(this_cpu))
112
                 release_console_sem();
113
 
114
         lockdep_on();
115
out_restore_irqs:
116
         raw_local_irq_restore(flags);
117
 
118
         preempt_enable();
119
         return printed_len;
120
}

作者“[No]left的博客”

上一篇:linux mysql备份
下一篇:linux快捷键