Linux内核中printf的实现(printk与vprintk)
大家应该都在找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的博客”
相关新闻>>
- 发表评论
-
- 最新评论 更多>>