2015-03-04 14 views
5

Jest plik i chciałbym go sprawdzić pod poll(), że zawartość się zmieniła.Użyj odpytywania() w celu sprawdzenia modyfikacji pliku

Na Raspi znajduje się plik o nazwie gpio, jeśli zmieniono wartość, poll() został wywołany przez POLLPRI, chciałbym zrobić to samo ze zwykłym plikiem.

Oto kod używam aby sprawdzić plik 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); 

a funkcja 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

Nie sądzę, że dobrze jest używać 'poll()' na sysfs, a zwłaszcza na _gpio_. GPIO nie pozwala na śledzenie, czy wartość się zmieniła, a sygnalizacja elektryczna AFAIK na to nie pozwala. Jak się tego spodziewasz z jądra? – myaut

+0

ten kod działa dla mnie dobrze na GPIO, ale chciałbym go zmienić na plik custome, jeśli jakieś dane dotrą do niego, wywołaj sondowanie. jeśli im nie było jasne :) –

+3

@myaut: faktycznie, możesz ** może ** użyć 'poll()' jeśli przerwanie jest włączone dla tego konkretnego pinu GPIO. Zalecane jest nawet w [Dokumentacja/gpio/sysfs.txt] (https://www.kernel.org/doc/Documentation/gpio/sysfs.txt) –

Odpowiedz

2

W Linuksie, w przeciwieństwie do swojej specjalnym pliku GPIO, nie można wzywania fd do otwartego zwykłego pliku w ten sposób.

Aby obejrzeć plik zmian, można użyć rodziny funkcji inotify. Wygodnie dla Ciebie używają deskryptora pliku, który można przekazać do poll() wraz z deskryptorem pliku GPIO, dzięki czemu możesz oglądać oba jednocześnie.

Tak, pewne drobne uzupełnienia/zmiany kodu:

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

Jesteś sondowanie na inotify FD, które można przeczytać, aby powrócić jeden więcej obserwował wydarzenia, które miały miejsce. Ponieważ ten kod ogląda tylko jeden plik na jedno wydarzenie, jesteśmy prawie pewni, co to jest wydarzenie, ale nadal musimy je odczytać z fd, wtedy możemy odczytać plik.

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

Oto file_watch_fd() funkcja:

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

A oto ready() funkcja:

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

(Ludzie doświadczenie w stosowaniu inotify zauważy, że uruchomiłem funkcję przybliżoną, aby ten przykład był prosty jak mogę)

+0

Nie, faktycznie 'poll()' na głównym inotify fd, "zegarek" fd jest zwracany w 'inotify_event's zwrócony, gdy czytasz inotify fd. Następnie możesz dopasować fd do wydarzenia, z którym plik się zmienił. W tym konkretnym przypadku istnieje tylko jeden plik, więc nie ma na to żadnego znaczenia. –

Powiązane problemy