linux的内核日志系统
0;
spin_lock_irq(&logbuf_lock); //如果要往外读数据,不希望在读的过程中数据发生变化,因此锁住环形数据缓冲区 while (!error && (log_start != log_end) && i < len) { //这里才是内核环形缓冲区真正消耗的地方. c = LOG_BUF(log_start); //得到一个字符 log_start ; //只有在这里才逻辑上清除环形缓冲区的数据 spin_unlock_irq(&logbuf_lock); error = __put_user(c,buf); buf ; i ; spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); ... } 我们看一下printk调用的vprintk内核函数: asmlinkage int vprintk(const char *fmt, va_list args) { unsigned long flags; int printed_len; char *p; static char printk_buf[1024]; static int log_level_unknown = 1; ... spin_lock_irqsave(&logbuf_lock, flags); //这个logbuf_lock自旋锁其实很重要,确保一次内核信息写的过程不会有别的写过程来捣乱,否则很多信息会揉在一起,比如hello和 world会变为hwellorold. printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args); for (p = printk_buf; *p; p ) { if (log_level_unknown) { if (p[0] != ''<'' || p[1] < '''' || p[1] > ''7'' || p[2] != ''>'') { emit_log_char(''<''); emit_log_char(default_message_loglevel ''''); emit_log_char(''>''); } log_level_unknown = 0; } emit_log_char(*p); if (*p == '' '') 拥有帝国一切,皆有可能。欢迎访问phome.net log_level_unknown = 1; } if (!cpu_online(smp_processor_id()) && system_state != SYSTEM_RUNNING) { spin_unlock_irqrestore(&logbuf_lock, flags); goto out; } if (!down_trylock(&console_sem)) { //如果现在可以得到设备的信号量,那么马上将数据显示到终端 console_locked = 1; spin_unlock_irqrestore(&logbuf_lock, flags); console_may_schedule = 0; release_console_sem(); //该函数具体显示数据 } else { spin_unlock_irqrestore(&logbuf_lock, flags);//本次的内核信息已经写入了内核环形缓冲,为了不阻碍别人写,释放掉自旋锁 } out: return printed_len; } 内核的环形缓冲有两个用途,一个是直接打印在屏幕上,还有一个就是可能用户空间的内核日志程序正在运行,因此这个函数完成了两个作用: void release_console_sem(void) { unsigned long flags; unsigned long _con_start, _log_end; unsigned long wake_klogd = 0; for ( ; ; ) { //打印向屏幕,注意,打印的时候也要确保logbuf_lock被拥有,不想在打印过程中发生缓冲区变化的事情 spin_lock_irqsave(&logbuf_lock, flags); wake_klogd |= log_start - log_end; //确保有数据,这个变量还作为是否唤醒do_syslog的睡眠队列的依据. if (con_start == log_end) break; /* Nothing to print */ _con_start = con_start; _log_end = log_end; con_start = log_end; //注意,log_end和log_start并没有变化,而是副本变化了,这是下面还要用到内核缓冲,不能写到了屏幕,信息就消耗了. spin_unlock_irqrestore(&logbuf_lock, flags); call_console_drivers(_con_start, _log_end); } console_locked |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |