发布时间:2014-09-05 16:58:29作者:知识屋
大家应该都在找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一键安装web环境全攻略 在linux系统中怎么一键安装web环境方法
Linux网络基本网络配置方法介绍 如何配置Linux系统的网络方法
Linux下DNS服务器搭建详解 Linux下搭建DNS服务器和配置文件
对Linux进行详细的性能监控的方法 Linux 系统性能监控命令详解
linux系统root密码忘了怎么办 linux忘记root密码后找回密码的方法
Linux基本命令有哪些 Linux系统常用操作命令有哪些
Linux必学的网络操作命令 linux网络操作相关命令汇总
linux系统从入侵到提权的详细过程 linux入侵提权服务器方法技巧
linux系统怎么用命令切换用户登录 Linux切换用户的命令是什么
在linux中添加普通新用户登录 如何在Linux中添加一个新的用户
2012-07-10
CentOS 6.3安装(详细图解教程)
Linux怎么查看网卡驱动?Linux下查看网卡的驱动程序
centos修改主机名命令
Ubuntu或UbuntuKyKin14.04Unity桌面风格与Gnome桌面风格的切换
FEDORA 17中设置TIGERVNC远程访问
StartOS 5.0相关介绍,新型的Linux系统!
解决vSphere Client登录linux版vCenter失败
LINUX最新提权 Exploits Linux Kernel <= 2.6.37
nginx在网站中的7层转发功能