有一个文件,我想检查poll()内容已更改.
在Raspi上有一个名为gpio value的文件,如果更改的值poll()是用POLLPRI触发的,我想对普通文件做同样的事情.
这是我用来检查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);
Run Code Online (Sandbox Code Playgroud)
和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;
}
Run Code Online (Sandbox Code Playgroud)
在 Linux 中,与您的特殊 GPIO 文件不同,您不能像这样将 fd 轮询到打开的普通文件中。
要查看文件的更改,您可以使用inotify函数系列。他们使用文件描述符方便您poll()与您的 GPIO 文件描述符一起传递,因此您可以同时观看两者。
因此,对您的代码进行一些小的添加/更改:
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);
Run Code Online (Sandbox Code Playgroud)
您正在对 inotify fd 进行轮询,您读取该文件以返回另一个已发生的监视事件。由于这段代码只针对一个事件观察一个文件,我们很确定事件是什么,但我们仍然需要从 fd 中读取它,然后我们才能真正读取文件。
if (fdset[1].revents & POLLIN) {
if (ready(fw_fd)) {
/* file has changed, read it */
}
}
Run Code Online (Sandbox Code Playgroud)
这是file_watch_fd()函数:
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;
}
Run Code Online (Sandbox Code Playgroud)
这是ready()函数:
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;
}
Run Code Online (Sandbox Code Playgroud)
(使用 inotify 的人会注意到我粗暴地处理了它的功能,以使这个例子尽可能简单)