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) && con->write)
368 con->write(con, &LOG_BUF(start), end - start);
369 }
370 }
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 &&amp; 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) && con->write)
368 con->write(con, &LOG_BUF(start), end - start);
369 }
370 }