2015-03-04 8 views
5

C'è un file e vorrei verificarlo con poll() che il contenuto è cambiato.Usa sondaggio() per verificare la modifica del file

Su Raspi è presente un file denominato gpio value, se il valore modificato poll() è stato attivato con POLLPRI, mi piacerebbe fare lo stesso con un file ordinario.

Ecco il codice che sto usando per verificare il file GPIO:

int gpio_fd = gpio_fd_open(); 
int timeout = POLL_TIMEOUT; 
struct pollfd fdset; 
int nfds = 1; 
char *buf[MAX_BUF]; 
int len; 
int rc; 
fdset.fd = gpio_fd; 
fdset.events = POLLPRI | POLLERR | POLLHUP | POLLNVAL; // POLLIN | | POLLOUT 
unsigned int c1, c2, c3; 
do{ 
    rc = poll(&fdset, 1, timeout); 

E la funzione gpio_fd_open:

int gpio_fd_open() { 
    printf("opening File: " SYSFS_GPIO_DIR "\n"); 

    int fd, len; 
    char buf[MAX_BUF]; 

    len = snprintf(buf, sizeof (buf), SYSFS_GPIO_DIR); 
    fd = open(buf, O_RDONLY | O_NONBLOCK); 
    if (fd < 0) { 
     perror("gpio/fd_open"); 
    } 
    return fd; 
} 
+0

Non penso che sia una buona idea usare 'poll()' su sysfs, e su _gpio_ in particolare. GPIO non consente di monitorare se il valore è cambiato, la segnalazione elettrica AFAIK non lo consente. Come ti aspetti dal kernel? – myaut

+0

questo codice funziona per me bene per GPIO, ma mi piacerebbe cambiarlo per file custome, se alcuni dati arrivano in esso fanno scattare il polling. se im non era chiaro :) –

+3

@myaut: in realtà, ** puoi ** usare 'poll()' se l'interrupt è abilitato per questo particolare pin GPIO. È anche raccomandato in [Documentation/gpio/sysfs.txt] (https://www.kernel.org/doc/Documentation/gpio/sysfs.txt) –

risposta

2

In Linux, a differenza con il file speciale GPIO, non è possibile eseguire il polling la fd in un file ordinario aperto come quello.

Per visualizzare un file per le modifiche è possibile utilizzare la famiglia di funzioni inotify. Convenientemente per te, usano un descrittore di file che può essere passato a poll() insieme al descrittore di file GPIO, in modo che tu possa guardarli entrambi allo stesso tempo.

Così, alcune aggiunte minori/modifiche al codice:

int fw_fd = file_watch_fd("/some/file/to/watch"); 
struct pollfd fdset[2]; 
int nfds = 2; 
int rc; 
fdset[0].fd = gpio_fd; 
fdset[0].events = POLLPRI | POLLERR | POLLHUP | POLLNVAL; 
fdset[1].fd = fw_fd; 
fdset[1].events = POLLIN; 
do { 
    rc = poll(fdset, nfds, timeout); 

cui si vuole prelevare il fd inotify, che si legge a restituire uno più eventi che si sono verificati guardato. Dato che questo codice guarda solo un file per un evento, siamo abbastanza sicuri di quale sia l'evento, ma dobbiamo ancora leggerlo dal file, quindi possiamo effettivamente leggere il file.

if (fdset[1].revents & POLLIN) { 
     if (ready(fw_fd)) { 
      /* file has changed, read it */ 
     } 
    } 

Ecco la file_watch_fd() funzione:

int file_watch_fd (const char * filename) { 
     static int  inot = ERR; 
     static int  iflags = IN_CLOEXEC | IN_NONBLOCK; 
     static uint32_t mask = IN_MODIFY; 
     int    watch; 

     if (inot == ERR) { 
       inot = inotify_init1(iflags); 
       if (inot == ERR) return ERR; 
     } 
     watch = inotify_add_watch(inot, filename, mask); 
     if (watch == ERR) return ERR; 
     return inot; 
} 

E qui è la funzione pronto():

int ready (int inot) { 
     uint64_t    buffer[8192]; 
     ssize_t     nr; 
     char *     p; 
     size_t     n; 
     struct inotify_event * evP; 
     int      ready = 0; 

     while ((nr = read(inot, (char *)buffer, sizeof(buffer))) > 0) { 
       for (p = buffer; p < buffer + nr; p += n) { 
         evP = (struct inotify_event *)p; 
         if (evP->mask & IN_MODIFY) ready = 1; 
         n = sizeof(struct inotify_event) + evP->len; 
       } 
     } 
     return ready; 
} 

(Persone esperienza nell'uso di inotify noterà che mi sono imbattuto nella funzionalità per mantenere questo esempio così semplice come posso)

+0

No, in effetti 'poll()' sul file inotify principale fd, il comando "watch" viene restituito nel file 'inotify_event 'restituito quando si legge il file inotify di fd. Quindi puoi abbinare il file fd all'evento con il quale il file è cambiato. In questo caso particolare, c'è solo un singolo file, quindi in realtà non ne vale la pena. –

Problemi correlati