« Home | QT embedded的Compiler Time錯誤 » | 1st working model (OLPC) » | 如何用RPM檔編譯Fedora core 5的kernel » | OLPC原型機 » | X Window出現could not open default font 'fixed' » | Combimouse » | Nokia 770使用經驗及中文問題 » | 另一個縮短城鄉差距的計畫 -- Intel在印度的“Jaagruti” » | 國內各種Linux套件下載的好地方 » | Meld: Linux上圖形化的diff/Merge工具 » 

2006/05/24 

Linux中的printk()追蹤

Linux中的printk()追蹤
Kernel Source Code版本為2.6.16

1.printk實作在kernel/printk.c中
2.printk透過在vprintk()中的release_console_sem()將text送到buffer中
3.release_console_sem利用call_console_drivers() 呼叫 一個底線的_call_console_drivers() -> 再呼叫 兩個底線的__call_console_drivers()
4.最後利用con->write() 將LOG_BUF寫出
註 con(console)則定義在linux/include/linux/console.h中

//以下原始碼為kernel/printk.c
514 asmlinkage int printk(const char *fmt, ...)
515 {
516 va_list args;
517 int r;
518
519 va_start(args, fmt);
520 r = vprintk(fmt, args);
521 va_end(args);
522
523 return r;
524 }
525
526 /* cpu currently holding logbuf_lock */
527 static volatile unsigned int printk_cpu = UINT_MAX;
528
529 asmlinkage int vprintk(const char *fmt, va_list args)
530 {
...
534 static char printk_buf[1024];
...
546
547 /* Emit the output into the temporary buffer */
548 printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
549
550 /*
551 * Copy the output into log_buf. If the caller didn't provide
552 * appropriate log level tags, we insert them here
553 */
554 for (p = printk_buf; *p; p++) {
...
605 }
606
...
627 release_console_sem();
...
749 void release_console_sem(void)
750 {
751 unsigned long flags;
752 unsigned long _con_start, _log_end;
753 unsigned long wake_klogd = 0;
754
755 for ( ; ; ) {
756 spin_lock_irqsave(&logbuf_lock, flags);
757 wake_klogd |= log_start - log_end;
758 if (con_start == log_end)
759 break; /* Nothing to print */
760 _con_start = con_start;
761 _log_end = log_end;
762 con_start = log_end; /* Flush */
763 spin_unlock(&logbuf_lock);
764 call_console_drivers(_con_start, _log_end);
765 local_irq_restore(flags);
766 }
767 console_locked = 0;
768 console_may_schedule = 0;
769 up(&console_sem);
770 spin_unlock_irqrestore(&logbuf_lock, flags);
771 if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait))
772 wake_up_interruptible(&log_wait);
773 }

396 static void call_console_drivers(unsigned long start, unsigned long end)
397 {
...
406 while (cur_index != end) {
...
416 while (cur_index != end) {
417 char c = LOG_BUF(cur_index);
418
419 cur_index++;
420 if (c == '\n') {
421 if (msg_level <> (end & LOG_BUF_MASK)) {
381 /* wrapped write */
382 __call_console_drivers(start & LOG_BUF_MASK,
383 log_buf_len);
384 __call_console_drivers(0, end & LOG_BUF_MASK);
385 } else {
386 __call_console_drivers(start, end);
387 }
388 }
389 }

362 static void __call_console_drivers(unsigned long start, unsigned long end)
363 {
364 struct console *con;
365
366 for (con = console_drivers; con; con = con->next) {
367 if ((con->flags & CON_ENABLED) &amp;& con->write)
368 con->write(con, &LOG_BUF(start), end - start);
369 }
370 }

About me

  • I'm Martin's blog 馬汀的部落格
  • From 中壢市, 桃園縣, Taiwan
  • -----BEGIN GEEK CODE BLOCK----- Version: 3.1 Comment: For info see http://www.geekcode.com GC/CS/CC/E/IT/TW d- s a C++++ L++++ P+ L++++ E--- W+++ N++ o+ K- w+++ O- M- V- PS+ PE++ Y+ PGP+ t 5- X++ R- tv- b+++ DI+ D-- G e+++ h+ r+ y+ z? ------END GEEK CODE BLOCK------ /**************************** 旅行是我生命的動力 它的樂趣從計劃旅行開始 我樂於分享旅行及Linux Kernel上的每一件事. ****************************/
My profile