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的博客”

 
 
