三 printk如何打印信息
来源:互联网 发布:mac aria2gui 下载 编辑:程序博客网 时间:2024/06/08 05:48
printk的定义
可变参数 参考va_list,va_start,va_arg,va_end可变参数
asmlinkage int printk(const char *fmt, ...){va_list args;//可变参数链表int r;#ifdef CONFIG_KGDB_KDBif (unlikely(kdb_trap_printk)) {va_start(args, fmt);r = vkdb_printf(fmt, args);va_end(args);return r;}#endifva_start(args, fmt);//获取第一个可变参数r = vprintk(fmt, args);//调用vprintk函数va_end(args);//释放可变参数链表指针return r;}
vprintk函数
asmlinkage int vprintk(const char *fmt, va_list args){int printed_len = 0;int current_log_level = default_message_loglevel;unsigned long flags;int this_cpu;char *p;boot_delay_msec();printk_delay();preempt_disable();raw_local_irq_save(flags);this_cpu = smp_processor_id();if (unlikely(printk_cpu == this_cpu)) {if (!oops_in_progress) {recursion_bug = 1;goto out_restore_irqs;}zap_locks();}lockdep_off();spin_lock(&logbuf_lock);printk_cpu = this_cpu;if (recursion_bug) {recursion_bug = 0;strcpy(printk_buf, recursion_bug_msg);printed_len = strlen(recursion_bug_msg);}printed_len += vscnprintf(printk_buf + printed_len,sizeof(printk_buf) - printed_len, fmt, args);p = printk_buf;if (p[0] == '<') {//处理打印级别字段unsigned char c = p[1];if (c && p[2] == '>') {switch (c) {case '0' ... '7': /* loglevel */current_log_level = c - '0';case 'd': /* KERN_DEFAULT */if (!new_text_line) {emit_log_char('\n');new_text_line = 1;}case 'c': /* KERN_CONT */p += 3;break;}}}for ( ; *p; p++) {if (new_text_line) {/* Always output the token */emit_log_char('<');emit_log_char(current_log_level + '0');emit_log_char('>');printed_len += 3;new_text_line = 0;if (printk_time) {//打印时间信息/* Follow the token with the time */char tbuf[50], *tp;unsigned tlen;unsigned long long t;unsigned long nanosec_rem;t = cpu_clock(printk_cpu);nanosec_rem = do_div(t, 1000000000);tlen = sprintf(tbuf, "[%5lu.%06lu] ",(unsigned long) t,nanosec_rem / 1000);for (tp = tbuf; tp < tbuf + tlen; tp++)emit_log_char(*tp);printed_len += tlen;}if (!*p)break;}emit_log_char(*p);if (*p == '\n')new_text_line = 1;}if (acquire_console_semaphore_for_printk(this_cpu))release_console_sem();lockdep_on();out_restore_irqs:raw_local_irq_restore(flags);preempt_enable();return printed_len;}
接着调用release_console_sem函数
void release_console_sem(void){unsigned long flags;unsigned _con_start, _log_end;unsigned wake_klogd = 0;if (console_suspended) {up(&console_sem);return;}console_may_schedule = 0;for ( ; ; ) {spin_lock_irqsave(&logbuf_lock, flags);wake_klogd |= log_start - log_end;if (con_start == log_end)break;/* Nothing to print */_con_start = con_start;_log_end = log_end;con_start = log_end;/* Flush */spin_unlock(&logbuf_lock);stop_critical_timings();/* don't trace print latency */call_console_drivers(_con_start, _log_end);start_critical_timings();local_irq_restore(flags);}console_locked = 0;up(&console_sem);spin_unlock_irqrestore(&logbuf_lock, flags);if (wake_klogd)wake_up_klogd();}EXPORT_SYMBOL(release_console_sem);
调用call_console_drivers函数
static void call_console_drivers(unsigned start, unsigned end){unsigned cur_index, start_print;static int msg_level = -1;BUG_ON(((int)(start - end)) > 0);cur_index = start;start_print = start;while (cur_index != end) {if (msg_level < 0 && ((end - cur_index) > 2) &&LOG_BUF(cur_index + 0) == '<' &&LOG_BUF(cur_index + 1) >= '0' &&LOG_BUF(cur_index + 1) <= '7' &&LOG_BUF(cur_index + 2) == '>') {msg_level = LOG_BUF(cur_index + 1) - '0';cur_index += 3;start_print = cur_index;}while (cur_index != end) {char c = LOG_BUF(cur_index);cur_index++;if (c == '\n') {if (msg_level < 0) {msg_level = default_message_loglevel;}_call_console_drivers(start_print, cur_index, msg_level);msg_level = -1;start_print = cur_index;break;}}}_call_console_drivers(start_print, end, msg_level);}
_call_console_drivers函数
static void _call_console_drivers(unsigned start,unsigned end, int msg_log_level){if ((msg_log_level < console_loglevel || ignore_loglevel) && console_drivers && start != end) {if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {/* wrapped write */__call_console_drivers(start & LOG_BUF_MASK,log_buf_len);__call_console_drivers(0, end & LOG_BUF_MASK);} else {__call_console_drivers(start, end);}}}
__call_console_drivers函数
遍历console_drivers数组
#define for_each_console(con) \for (con = console_drivers; con != NULL; con = con->next)
调用console的写方法
static void __call_console_drivers(unsigned start, unsigned end){struct console *con;for_each_console(con) {if ((con->flags & CON_ENABLED) && con->write &&(cpu_online(smp_processor_id()) ||(con->flags & CON_ANYTIME)))con->write(con, &LOG_BUF(start), end - start);//调用console的写方法}}
console_drivers链表在register_console中会设置
二 console 设备驱动
- 三 printk如何打印信息
- 三 printk如何打印信息
- [Linux] 如何查看printk打印的信息?
- printk无法打印信息
- printk信息打印
- 如何查看Linux内核中printk打印的信息?
- ubuntu中printk打印信息
- 将驱动中的printk信息打印出来
- 禁止内核打印内核信息(printk)
- 控制调试信息的打印(printk,printf)
- printk打印
- 用函数printk打印内核信息的方法
- printk信息打印到指定文件 终端 网络
- ubuntu/centos printk 终端中不能打印信息及解决办法
- 用函数printk打印内核信息的方法
- 模块中printk信息打印到指定文件 终端 网络
- ubuntu/centos printk 终端中不能打印信息及解决办法
- Linux中的Printk与dmesg功能(模块编译,printk无法打印信息)
- 如何确定matlab里的intel MKL版本?
- 一篇不错的v4l2
- 网页计时功能实现
- java中的大整数类BigInteger处理大整数——小小钟
- eclipse输入字母可以类提示(不用alt+/)和java方法设置快捷键
- 三 printk如何打印信息
- orcad/allegro使用心的
- 算法 求N的阶层 N!
- 主外键的疑惑
- Android 如何让EditText不自动获取焦点
- HDU 1175 连连看
- 物联网操作系统是否需要基于Java和虚拟机进行构筑
- html 资源备份
- 开启我的CSDN博文之旅