As we already discussed, the ELF's workbench area is really dynamic and a lot of synchronization is going on. But not everything is that entangled and interactive. For some tasks, ELFs just want to wait until some other ELF has put something into the warehouses and become active afterwards. In previous years, ELFs just visited the warehouse from time to time (for example daily) to see if the desired object (e.g., a plank of hard wood) was put into the warehouse. As you imagine, this is time consuming and it also induces latency. If the hard wood arrived shortly after you visited the warehouse, you would only notice on the next day. Wouldn't it be great if the warehouse would inform us directly about the arrival of the hard wood?
As yesterday's task was surely very challenging, we will have a much easier day today. Also, because its my birthday today :-). Today, we will look at the famous inotify(7) interface. With this interface, applications can watch for changes within the file system, so you can write programs that monitor a directory and perform an action if the directory or its contents were changed (by someone).
And actually, this very kernel interface changed my life for the better: In former times, the tail(1) program was poll based and checked its monitored files every second with the -f
(for follow) flag. However, this lead to a 1-second delay until lines that my other programs wrote to the log file appeared on the terminal. With inotify, tail -f
nowadays gets informed on the file change and immediately can present me with the line on my terminal. This saves me a lot of adrenaline and frustration that I've had with computers. What a gift for my birthday!
OK, so what is special about inotify? Today, I will not talk too much about inotify itself as it is wonderfully described in inotify(7). But I will talk about the usage of file descriptors to get a hold of in-kernel things (we use the word object
to sound fancy). When we create a new inotify object in the kernel with inotify_init(2), we get a file descriptor as a return value. And we are supposed to use read(2) to retrieve inotify events. Isn't that wild. The inotify object is surely no file that has a beginning or an end. Nevertheless, it is a stream of events that we want to retrieve. Additionally, the read system call blocks if there is no event available for consumption. Therefore, using the read()
operation on this event stream is only weird on the first glance but actually fits if you think about it.
But, there is something weird about these inotify-files
: We cannot read byte-wise from this event stream. So a
read(inotify_fd, buffer, /*size = */ 1)
will always return -1
. The kernel will only deliver complete events to user-space, which makes the in-kernel implementation much easier as the kernel does not has to track half-read events. Therefore, we also have to use a buffer that is large enough to consume at least one event.
Write a program that watches the current working directory ("."
) and prints all IN_OPEN | IN_ACCESS | IN_CLOSE
events. Print each event as an individual line.
Start your program in your 05-inotify
directory and compare its output to the output of the strace cat Makefile
call, which traces all system calls of the cat
program while it reads the file Makefile
from disk. You should be able to correlate the open()/read()/close()
system calls to inotify events that you print on the terminal.
My outputs look like this:
$ ./inotify
./Makefile [open]
./Makefile [access]
./Makefile [close_nowrite,close]
And in another terminal, while ./inotify
is running and listening to events.
$ strace cat Makefile
openat(AT_FDCWD, "Makefile", O_RDONLY) = 3
...
read(3, "inotify: inotify.c\n\tgcc inotify."..., 131072) = 151
....
close(3) = 0
Last modified: 2023-12-01 15:52:27.945309, Last author: , Permalink: /p/advent-05-inotify
Vacancies of TU Braunschweig
Career Service' Job Exchange
Merchandising
Term Dates
Courses
Degree Programmes
Information for Freshman
TUCard
Technische Universität Braunschweig
Universitätsplatz 2
38106 Braunschweig
P. O. Box: 38092 Braunschweig
GERMANY
Phone: +49 (0) 531 391-0