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)
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
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 :) –
@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) –