There is a file and I would like to check it with poll()
that the contents have changed.
On Raspi there is a file called gpio value, if the value changed the poll()
was triggered with POLLPRI, I would like to do the same with an ordinary file.
Here is the code I am using to check the GPIO file:
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);
And the gpio_fd_open function:
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;
}
In Linux, unlike with your special GPIO file, you can not poll the fd to an open ordinary file like that.
To watch a file for changes you can use the inotify
family of functions. Conveniently for you they use a file descriptor which can be passed to poll()
along with your GPIO file descriptor, so you can watch both at the same time.
So, some minor additions/changes to your code:
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);
You are polling on the inotify fd, which you read to return one more watched events which occurred. Since this code is only watching one file for one event, we're pretty sure what the event is, but we still need to read it out of the fd, then we can actually read the file.
if (fdset[1].revents & POLLIN) {
if (ready(fw_fd)) {
/* file has changed, read it */
}
}
Here is the file_watch_fd() function:
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;
}
And here is the ready() function:
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;
}
(People experience in the use of inotify will notice that I ran roughshod over the functionality of it to keep this example as simple as I can)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With