Использование read с inotify - PullRequest
13 голосов
/ 06 марта 2011

Я изучал вызов inotify, но я все еще немного вял, когда дело доходит до интерфейса чтения. Это наиболее релевантные ресурсы, которые я смог найти относительно того, как правильно взаимодействовать с inotify, используя read (2):

Они оба реализуют это одинаково, сначала они определяют следующие размеры:

#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 )

И затем они используют их таким образом:

length = read( fd, buffer, BUF_LEN );  

if ( length < 0 ) {
    perror( "read" );
}  

while ( i < length ) {
    struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
    /* some processing */
    i += EVENT_SIZE + event->len;
}

Теперь мы знаем, что имя является частью struct inotify_event и имеет переменную длину. Итак, нельзя ли обрезать последнее inotify_event в буфере?

Предположим, есть 1023 inotify_events с путем в 16 байтов и один с путем в 32 байта. Что будет потом? Будет ли позже усечено? Или ядро ​​увидит, что оно не помещается в буфер, и оставит все это в целом?

1 Ответ

8 голосов
/ 09 ноября 2012

Базовое использование

В соответствии с inotify (7) , вы можете использовать FIONREAD ioctl, чтобы узнать, сколько данных доступно для чтения, и соответственно изменить размер вашего буфера.Вот некоторый (очень грубый) код, который может выполнить это:

unsigned int avail;
ioctl(inotify_fd, FIONREAD, &avail);

char buffer[avail];
read(fd, buffer, avail);

int offset = 0;
while (offset < avail) {
    struct inotify_event *event = (inotify_event*)(buffer + offset);

    // Insert logic here
    my_process_inotify_event(event);

    offset = offset + sizeof(inotify_event) + event->len;
}

Более надежное использование

inotify-tools предоставляет высокоуровневый интерфейс для inotify.Вы можете использовать его вместо доступа к inotify или посмотреть, как он реализует inotifytools_next_events для безопасного и надежного чтения всех доступных событий.

Частичные события и усечение

В ответна ваши вопросы об усечении я не думаю, что ядро ​​когда-либо возвратит частичное inotify_event или усечет inotify_event, если указанный буфер слишком мал для всех событий.Следующий абзац из man-страницы inotify (7) предлагает следующее:

Поведение, когда буфер, переданный read (2), слишком мал, чтобы возвращать информацию о следующем событии, зависит от версии ядра: inядра до 2.6.21, read (2) возвращает 0;начиная с ядра 2.6.21, read (2) завершается с ошибкой EINVAL.

Как и следующие комментарии от inotifytools.c :

// oh... no.  this can't be happening.  An incomplete event.
// Copy what we currently have into first element, call self to
// read remainder.
// oh, and they BETTER NOT overlap.
// Boy I hope this code works.
// But I think this can never happen due to how inotify is written.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...