How to read ring buffer within linux kernel space? - linux

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:
Is ring buffer inside kernel space?
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.)

What you are looking for is /proc/kmsg. This is the kernel ring buffer!
Yes, this is inside kernel space. Any process trying to read it should have super user privileges to read it!
How to read it the ring buffer? Here is a beautiful illustration from IBM Developerworks
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-
http://www.makelinux.net/ldd3/chp-4-sect-2
http://www.ibm.com/developerworks/linux/library/l-kernel-logging-apis/index.html
http://oguzhanozmen.blogspot.in/2008/09/kernel-log-buffering-printk-syslog-ng.html

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.

Related

Is there a real file for stream i/o in linux?

I confused in concept of i/o stream in the linux.
There is 3 types of stream: standard input. standard output and standard error.
Is there a real file in the ram or hard disk for stdin, stdout and stderr?
For example: kernel writes all keyboard inputs to a stdin file? and then bash(for example) read this file?
And if this true, that's mean any software can read this file in any time?
Every process has (at least initially) the standard stdin/stdout/stderr file handles opened for it. Every process also has a representation in /proc, which is a virtual file system created by the kernel to access all kinds of stuff about the processes. So...
marc#panic:~$ ps
PID TTY TIME CMD
4367 pts/0 00:00:00 bash <--- my bash process
4394 pts/0 00:00:00 ps
marc#panic:~$ cd /proc/4367/fd <---my bash processes's /proc file descriptors
marc#panic:/proc/4367/fd$ ls -l
total 0
lrwx------ 1 marc marc 64 Nov 17 11:17 0 -> /dev/pts/0
lrwx------ 1 marc marc 64 Nov 17 11:17 1 -> /dev/pts/0
lrwx------ 1 marc marc 64 Nov 17 11:17 2 -> /dev/pts/0
lrwx------ 1 marc marc 64 Nov 17 11:18 255 -> /dev/pts/0
files 0, 1, 2 correspond to stdin, stdout, stderr, and they're simply symlinks to the particular pseudo terminal my login session is using.
I wouldn't call these real files, but:
You can use /dev/stdout etc on Linux.

bash 4.3.42 .: is /dev/fd/1 incorrect after redirecting or closing stdout?

I redirect (or close) stdout but /dev/fd (and /proc/self/fd) still shows stdout going to the tty:
% exec 1>log
% ls -l /dev/fd/ >/dev/stderr
and get this
total 0
lrwx------ 1 guest guest 64 Sep 22 15:31 0 -> /dev/pts/1
l-wx------ 1 guest guest 64 Sep 22 15:31 1 -> /dev/pts/1
lrwx------ 1 guest guest 64 Sep 22 15:31 2 -> /dev/pts/1
lr-x------ 1 guest guest 64 Sep 22 15:31 3 -> /proc/14374/fd/
(ls -l /proc/self/fd/ prints the same).
The command
% date
does not print date on screen but
% cat log > /dev/stderr
Tue Sep 22 15:59:48 PDT 2015
shows that the output of date command has been written to 'log'
I can close fd 1 in a c program (or via exec 1>&- ) and /dev/fd/1 still shows it pointing to my tty. Anyone have an explanation for this behavior?
Fedora fc22 4.1.6-201 & Archlinux version??? on my Raspberry PI
You closed file descriptor 1 of the shell, as you expected. However, when you checked to see what file descriptor 1 was, you used:
ls /dev/fd > /dev/stderr
But what’s that > do? For that single command, it reopens file descriptor 1, pointing to the file /dev/stderr. Hence, since /dev/stderr pointed to your pseudoterminal, ls’s file descriptor 1 will also point to your pseudoterminal, and /dev/fd reflects that. If you wanted to print out the file descriptors of the shell’s process, rather than ls’s process, you’d need to specifically say that:
ls -l /proc/$$/fd > /dev/stderr

How to see which file are in use in Linux

I have a question how can I see which file are in use in linux. To be honest this OS is not the normal version of linux it is very crippled so for example there is no command like "lsof". I found command "strace" but this is no what I looking for. I hear that I can list this file with hacking kernel?
I want to see which file are in use because on this machine is a little free space and I want to delete file which are no in use when the program is running.
I'm sorry for my weak english.
You can inspect the open files by process by walking the /proc virtual filesystem
Every process running has an entry in /proc/PID. There's a directory in each process directory called 'fd', that represents the processes currently opened file descriptors. These appear as links to the actual resources.
e.g. on a VM I have running
root#wvm:/proc/1213/fd# pidof dhclient
1213
root#wvm:/proc/1213/fd# cd /proc/1213/fd
root#wvm:/proc/1213/fd# ls -l
total 0
lrwx------ 1 root root 64 Apr 8 09:11 0 -> /dev/null
lrwx------ 1 root root 64 Apr 8 09:11 1 -> /dev/null
lrwx------ 1 root root 64 Apr 8 09:11 2 -> /dev/null
lrwx------ 1 root root 64 Apr 8 09:11 20 -> socket:[4687]
lrwx------ 1 root root 64 Apr 8 09:11 21 -> socket:[4688]
l-wx------ 1 root root 64 Apr 8 09:11 3 -> /var/lib/dhcp/dhclient.eth0.leases
lrwx------ 1 root root 64 Apr 8 09:11 4 -> socket:[4694]
lrwx------ 1 root root 64 Apr 8 09:11 5 -> socket:[4698]
root#wvm:/proc/1213/fd#
Looking at the kernel process information for 'dhclient' - I find its pid, and then look in the fd subdirectory for this process id. It has a small set of open descriptors - stdin, stdout and stderr ( 0,1,2 ) have all been attached to /dev/null , there's four sockets open, but file descriptor 3 is attached to a data file /var/lib/dhcp/dhclient.eth0.leases
So you could duplicate the functionality of lsof using shell tools to walk /proc and filter out the file names from these links.
Are you able to use "top" command? if so then this should show you the list of all the top OS utilizing operations running on linux. You can do
ps -ef|grep <process_no>
this would give the details of it. Either can stop that process or kill it using
kill -9 <process no>
Use the lsof command to list all open files by process.

Device node at /dev/tty* not getting created for uart serial driver

I have written a simple UART serial driver in embedded Linux running busybox with mdev rules. I have provided .dev_name as "ttyC2C" in my driver code.
static struct uart_driver serial_omap_reg = {
.owner = THIS_MODULE,
.driver_name = "Omap-C2C-Serial",
.dev_name = "ttyC2C",
.nr = OMAP_MAX_HSUART_PORTS,
.cons = NULL,
};
However the node is getting created in
./sys/devices/platform/omap_c2c_uart.0/tty/ttyC2C0
./sys/class/tty/ttyC2C0
/ # ls -l ./sys/class/tty/ttyC2C0
lrwxrwxrwx 1 root 0 0 Jan 1 00:14 ./sys/class/tty/ttyC2C0 -> ../../devices/platform/omap_c2c_uart.0/tty/ttyC2C0
/ # ls -l ./sys/devices/platform/omap_c2c_uart.0/tty/ttyC2C0
-r--r--r-- 1 root 0 4096 Jan 1 00:14 dev
lrwxrwxrwx 1 root 0 0 Jan 1 00:14 device -> ../../../omap_c2c_uart.0
drwxr-xr-x 2 root 0 0 Jan 1 00:14 power
lrwxrwxrwx 1 root 0 0 Jan 1 00:14 subsystem -> ../../../../../class/tty
-rw-r--r-- 1 root 0 4096 Jan 1 00:14 uevent
/ #
The mdev rules for tty are:
tty 0:5 0666
tty.* 0:0 0620
How to get device node as /dev/ttyC2C ?
You are confusing two things. The sysfs nodes you are seeing are indeed maintained by the kernel based on the kobject hierarchy. However device nodes are entirely a user space problem and can exist anywhere (although by convention are under /dev).
So by hand you would first find the major:minor numbers:
cat /sys/class/tty/ttyC2C0/dev
And then:
mknod /dev/ttyC2C0 c ${MAJOR} ${MINOR}
However as you have already indicated you are using the fork of udev, mdev to handle the user space creation of device nodes. However the matching rules look odd to me. I assume mdev has the equivalent of udevadm which should help you write the matching rules. For example my USB tty driver can be queried like this:
udevadm info -a -p /sys/class/tty/ttyUSB0
And looking at the tree produced I can see a list of udev attributes which I could use to match. So in my case:
KERNEL=="ttyUSB0", DRIVERS=="ftdi_sio", NAME="ttyUSB0"
Would be enough to match (although my distro has a lot more complex matching rules to deal with dynamic setups).
I'm guessing but I suspect the mapping rule you want would look more like:
KERNEL=="ttyC2C", NAME="ttyC2C"
Although you might need a bit more to ensure you get device nodes created for each port (minor number?).
Does adding a specific mdev rule to your /etc/mdev.conf for ttyC2C resolve your problem ?
Something like one of the following ?
ttyC2C[0-9]+ root:tty 620
or
ttyC2C[0-9]+ root:tty 620 #/bin/ln -sf $MDEV ttyC2C

How to reroute stdout, stderr back to /dev/tty

I just ssh-ed to some remote server and found that stdout and stderr of all commands/processes I am trying to run in bash is redirected to somewhere.
So, I got following questions
How to detect:
1) Which file stdout, stderr is beeing rerouted in Linux?
and
2) And how reroute by default stdout and stderr back to /dev/tty?
Thank you in advance.
A command that should do literally what you asked for in (2) is
exec >/dev/tty 2>&1
But I suspect that your analysis of the problem is incorrect. It would be useful to see the output of ssh -v ... (where ... is whatever arguments you typed in your original ssh command).
The command:
ls -l /proc/$$/fd/{1,2}
will show you which files are open as stdout (file descriptor 1) and stderr (file descriptor 2).
An answer to your first question could be found in /proc/self/fd. It contains symlinks to the files (or other things, pipes, sockets, etc) that your bash instance is connected to.
root#mammon:~# ls -l /proc/self/fd
total 0
lrwx------ 1 root root 64 May 21 02:18 0 -> /dev/pts/3
lrwx------ 1 root root 64 May 21 02:18 1 -> /dev/pts/3
lrwx------ 1 root root 64 May 21 02:18 2 -> /dev/pts/3
lr-x------ 1 root root 64 May 21 02:18 3 -> /proc/15529/fd/
root#mammon:~# ls -l /proc/self/fd < /dev/null
total 0
lr-x------ 1 root root 64 May 21 02:18 0 -> /dev/null
lrwx------ 1 root root 64 May 21 02:18 1 -> /dev/pts/3
lrwx------ 1 root root 64 May 21 02:18 2 -> /dev/pts/3
lr-x------ 1 root root 64 May 21 02:18 3 -> /proc/15536/fd/
root#mammon:~# ls -l /proc/self/fd | cat
total 0
lrwx------ 1 root root 64 May 21 02:18 0 -> /dev/pts/3
l-wx------ 1 root root 64 May 21 02:18 1 -> pipe:[497711]
lrwx------ 1 root root 64 May 21 02:18 2 -> /dev/pts/3
lr-x------ 1 root root 64 May 21 02:18 3 -> /proc/15537/fd/
root#mammon:~#
In the first example, you can see the first 3 file descriptors (which are the standard output, input, and error, respectively) all point to my pseudo-terminal /dev/pts/3. In the second example I've redirected the input to /dev/null, so the standard input file descriptor points to /dev/null. And in the final example I've sent the output of ls to cat through a pipe, and the standard input file descriptor reflects this. As far as I know there is no way to find which process has the other end of the pipe. In all examples there is the fourth file descriptor that represents the handle that ls has for reading /proc/self/fd. In this case it says /proc/15537 because /proc/self is in fact a symlink to /proc/pid where pid is the PID of the process accessing /proc/self.
It can only be done if your longing shell is started with a pipe to tee command with another console as a parameter.
Let me explain.
If you are logging in /dev/tty1 and someone else is logging in /dev/tty2. If you start your shell (bash) by following command all the STDOUT/STDERR will be rerouted/copied to another shell (/dev/tty2 in this case).
bash 2>&1 | tee /dev/tty2
So, someone sitting in /dev/tty2 will see all of your activity.
If someone logins shell is /bin/bash 2>&1 | tee /dev/tty2 instead of /bin/bash It'll happen every time he logs in. But I am not sure login shell can be set that way.
If someone reroutes all the output of your shell this way you can check it just by checking if any tee is running in background.
ps ax | grep tee
This will output something like
tee /dev/tty2

Resources