20
votes

I'm writing a Linux character driver which can print system logs in user space. Just as the command 'dmesg' does. I've learned that all the log that we print with 'printk' will be sent to a space named ring buffer. So I have the questions:

  1. Is ring buffer inside kernel space?
  2. If so, how can I read the ring buffer inside kernel space? (I've tried to read the source code of dmesg.c. But it did not help.)
2

2 Answers

45
votes

What you are looking for is /proc/kmsg. This is the kernel ring buffer!

  1. Yes, this is inside kernel space. Any process trying to read it should have super user privileges to read it!

  2. How to read it the ring buffer? Here is a beautiful illustration from IBM Developerworks

Reading the Kernel Ring Buffer

dmesg would be your first resort! How does dmesg accomplish its task? By a call to syslog()! How does syslog do its job? Through the system call interface which in turn call do_syslog(). do_syslog() does the finishing act like this.

Here are a few more resources to get you more info about /proc/kmsg and kernel logging in general-

  1. http://www.makelinux.net/ldd3/chp-4-sect-2

  2. http://www.ibm.com/developerworks/linux/library/l-kernel-logging-apis/index.html

  3. http://oguzhanozmen.blogspot.in/2008/09/kernel-log-buffering-printk-syslog-ng.html

5
votes

This is further to Pavan's very good answer (taught me a lot):

Different distro may redirect the output of /proc/kmsg to any physical log files or virtual devices (/dev/xxx) they like. But "/proc/kmsg" is the original source of the kernel log, because the kernel implement its ring buffer operation inside fs/proc/kmsg.c:

static const struct file_operations proc_kmsg_operations = {
        .read           = kmsg_read,
        .poll           = kmsg_poll,
        .open           = kmsg_open,
        .release        = kmsg_release,
        .llseek         = generic_file_llseek,
};

So how you see the output is this:

sudo tail -f /proc/kmsg

But you can only see all the messages generated AFTER you have issued this command - all previous messages in the ring buffer will not be printed out. And so to see the physical file output, you can search for the user of "/proc/kmsg":

sudo lsof |grep proc.kmsg

And my machine indicated this:

rsyslogd  1743               syslog    3r      REG                0,3          0 4026532041 /proc/kmsg
in:imuxso 1743 1755          syslog    3r      REG                0,3          0 4026532041 /proc/kmsg
in:imklog 1743 1756          syslog    3r      REG                0,3          0 4026532041 /proc/kmsg
rs:main   1743 1757          syslog    3r      REG                0,3          0 4026532041 /proc/kmsg

So now it is pid 1743, let's see the files fd opened by 1743:

sudo ls -al /proc/1743/fd

lrwx------ 1 root   root   64 Dec 11 08:36 0 -> socket:[14472]
l-wx------ 1 root   root   64 Dec 11 08:36 1 -> /var/log/syslog
l-wx------ 1 root   root   64 Dec 11 08:36 2 -> /var/log/kern.log
lr-x------ 1 root   root   64 Dec 11 08:36 3 -> /proc/kmsg
l-wx------ 1 root   root   64 Dec 11 08:36 4 -> /var/log/auth.log

And so there you go, pid 1743 is rsyslogd, and it redirect the output of /proc/kmsg to files like /var/log/syslog and /var/log/kern.log etc.