快速业务通道

linux的内核日志系统

作者 佚名技术 来源 Linux系统 浏览 发布时间 2012-04-15
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 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号