Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are watch descriptors really ? (Linux inotify subsystem)

Tags:

c

linux

unix

I'm currently using the inotify() system for monitoring the activity of certain directories in the filesystem in my C code.

Now, the procedure for using one of these things is as follows. You take an integer(say event_notifier), turn it into an inotify descriptor using inotify_init(), like so

event_notifier=inotify_init();

Now, suppose I want to keep a watch over events on multiple directories. I will then add watches to this event_notifier over those directories

wd1 = inotify_add_watch(event_notifier,"/../path..to..directory1/../",IN_ALL_EVENTS);
wd2 = inotify_add_watch(event_notifier,"/../path..to..directory2/../",IN_ALL_EVENTS);
wd3 = inotify_add_watch(event_notifier,"/../path..to..directory3/../",IN_ALL_EVENTS);
                            . . . . 
wdn = inotify_add_watch(event_notifier,"/../path..to..directoryn/../",IN_ALL_EVENTS);

Now, I can add watches over multiple directories. Each of these calls returns a "watch descriptor" (wd1, wd2, wd3.. wdn above). Whenever an event occurs in any of the directories, the inotify system sends an event to the inotify file descriptor event_notifier along with the watch descriptor (wd1, wd2...wdn) corresponding to that particular "watched directory"

When an event comes in, I can read the event_notifier for an array of struct inotify_event s. This inotify_event structure has the following fields :

struct inotify_event  
{
  int wd; //Watch descriptor   
   ...  
  uint32_t len; //Size of 'name' field  
  char name[];  //null terminated name  
}

To read events, you simply do

read(event_notifier, buffer, sizeof(buffer))
struct inotify_event* event;
event=(struct inotify_event*)buffer; //Assuming only one event will occur

I am interested in finding out which directory the notification came from. But when I stat() the watch descriptor, it gives me nothing

struct stat fileinfo;
fstat(event->wd, &fileinfo);
printf("\n Size of file is %l",fileinfo_st.size);

Even readlink() on /proc/self/fd/event->fd did not yield any filename.

char filename[25]; 
readlink("/proc/self/fd/event-wd",filename,sizeof(filename));
printf("\n The filename is %s",filename);

I have two questions :

1) What is the watch descriptor pointing to exactly ? What is it good for ?
2) How can I tell which directory the notification is coming from ?

like image 876
Arjun J Rao Avatar asked Jun 21 '14 13:06

Arjun J Rao


People also ask

What is inotify file descriptor?

The inotify API identifies events via watch descriptors. It is the application's responsibility to cache a mapping (if one is needed) between watch descriptors and pathnames. Be aware that directory renamings may affect multiple cached pathnames.

What are inotify watches?

Inotify Watch helps to keep track of the file changes under the directories on "watch" and report back to the application in a standard format using the API calls. We can monitor multiple file events under the watched directory using the API calls.

What is inotify in Linux?

inotify (inode notify) is a Linux kernel subsystem created by John McCutchan, which monitors changes to the filesystem, and reports those changes to applications. It can be used to automatically update directory views, reload configuration files, log changes, backup, synchronize, and upload.

What is inotify instance?

An "instance" is single file descriptor, returned by inotify_init() . A single inotify file descriptor can be used by one process or shared by multiple processes, so they are rationed per-user instead of per-process. A "watch" is a single file, observed by inotify instance.


1 Answers

What is the watch descriptor pointing to exactly ? What is it good for ?

The watch descriptor isn't a file system object or a file descriptor. It is a resource descriptor used by the inotify subsystem to link events to a watched resource and gives you the possibility to specify certain watches when removing them.

You should also note that the number of possible "open" watch descriptors is limited on the system. You can get the maximum value using:

cat  /proc/sys/fs/inotify/max_user_watches

If you for any reason need more than this value, you can set the value using:

sudo sysctl -w fs.inotify.max_user_watches=XXXXXX

How can I tell which directory the notification is coming from ?

Using the inotify extension only it is not possible to get the full path to the file (directory) from the event structures. Your application code will need special lookup tables storing links between watch descriptors and full path names. I did that once in PHP, because I also felt I needed that. You may have a look at the code on Github. Like I said, it's PHP but it may help to understand what I'm doing. (The inotify system call signatures are the same in PHP and C)

like image 92
hek2mgl Avatar answered Sep 28 '22 09:09

hek2mgl