Domanda Usando leggi con inotify


Ho studiato la chiamata inotify, ma sono ancora un po 'instabile quando si tratta dell'interfaccia di lettura. Queste sono le risorse più rilevanti che ho trovato su come interfacciare correttamente con inotify usando read (2):

Entrambi lo implementano nello stesso modo, prima definiscono le seguenti dimensioni:

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

E poi li usano in questo modo:

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;
}

Ora, sappiamo che il nome fa parte di struct inotify_event e che ha una lunghezza variabile. Quindi, non è possibile troncare l'ultimo inotify_event nel buffer?

Supponiamo che ci siano 1023 inotify_events con un percorso di 16 byte e uno con un percorso di 32 byte. Cosa succederà allora? Il più tardi sarà troncato? O il kernel vedrà che non si adatterà al buffer e lascerà tutto del tutto?


13
2018-03-06 17:09


origine


risposte:


Utilizzo di base

Secondo inotify (7), puoi usare l'ioctl di FIONREAD per scoprire quanti dati sono disponibili da leggere e dimensionare il buffer di conseguenza. Ecco un codice (molto approssimativo) che può realizzare questo:

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;
}

Uso più robusto

inotify-tools fornisce un'interfaccia di livello superiore per inotify. Puoi usarlo invece di accedere a inotify, o puoi vedere come lo implementa inotifytools_next_events leggere in modo sicuro e affidabile tutti gli eventi disponibili.

Eventi parziali e troncamenti

In risposta alle tue domande sul troncamento, non penso che il kernel restituirà mai un inotify_event parziale o troncerà un inotify_event se il buffer dato è troppo piccolo per tutti gli eventi. Il seguente paragrafo della manpage inotify (7) suggerisce questo:

Il comportamento quando il buffer dato a read (2) è troppo piccolo per restituire informazioni sul prossimo evento dipende dalla versione del kernel: nei kernel precedenti alla 2.6.21, read (2) restituisce 0; dal kernel 2.6.21, read (2) fallisce con l'errore EINVAL.

Come fanno i seguenti commenti da 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.

9
2017-11-08 20:37