gpt4 book ai didi

c - poll() 不阻塞,立即返回

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:34:49 54 4
gpt4 key购买 nike

我正在尝试使用 poll() 通过 sysfs 捕获 GPIO 中断。我在第三个位置有 -1 所以它可以阻挡,但它似乎总是在返回。我已经在 SO 上查看了一些类似的帖子。特别是 this (1) , this (2) , 和 this (3) .

在 (1) 中,通过在调用 poll() 之前放置一个虚拟的 read() 解决了这个问题。如果我这样做(请参阅代码中注释的 read())。我的代码在循环中运行一次并在第二次 poll() 上永远阻塞。

在 (2) 中,这可能是一种解释,但并没有真正为我的问题提供解决方案。

在 (3) 中,我的 read() 之前已经有一个 lseek()

当 gpio 的 value 发生变化时,我怎样才能让这个 poll() 阻塞并只在中断中返回?

这是代码片段:

int read_gpio(char *path, void (*callback)(int)){
int fd;
char buf[11];
int res = 0;
char c;
int off;
struct pollfd gpio_poll_fd = {
.fd = fd,
.events = POLLPRI,
.revents = 0
};
for(;;){

gpio_poll_fd.fd = open(path, O_RDONLY);
if(fd == -1){
perror("error opening file");
return -1;
}
// char c;
// read(fd,&c,1);
LOGD("for begins");
res = poll(&gpio_poll_fd,1,-1);
LOGD("polling ended");
if(res == -1){
perror("error polling");
break;
}

if((gpio_poll_fd.revents & POLLPRI) == POLLPRI){
LOGD("POLLPRI");
off = lseek(fd, 0, SEEK_SET);
if(off == -1) break;
memset(&buf[0], 0, 11);
size_t num = read(fd, &buf[0], 10*sizeof(char));
LOGD("Before callback");
callback(atoi(buf));
LOGD("After Callback");
}
if((gpio_poll_fd.revents & POLLERR) == POLLERR) {
//seems always to be true ..
//LOGD("POLLERR");
}
close(fd);
LOGD("for ends");

}
LOGD("for exits");

return 0;
}

注意:当我在 Android JNI 上执行此操作时,我一直在从 LOGD()

获取调试信息

更新:按照 jxh 评论中的建议,我已经像这样安排了结构,尽管现在它无限期地阻塞在 poll() 上。当 value 的内容从外部施加的电压改变时,POLLPRI 不会变高,并且 poll() 不会返回:

int read_gpio(char *path, void (*callback)(int)){
int fd = open(path, O_RDONLY);
if(fd == -1){
perror("error opening file");
return -1;
}
char buf[11];
int res, off;
char c;
struct pollfd pfd = {
.fd = fd,
.events = POLLPRI,
.revents = 0
};
for(;;){
LOGD("for begins");
// dummy read causes poll never to run
// lseek() alone here cause poll never to run
// read(fd, &buf[],1);
// lseek(fd, 0, SEEK_SET);
res = poll(&pfd,1,-1);
LOGD("polling ended");
if(res == -1){
perror("error polling");
break;
}

if((pfd.revents & POLLPRI) == POLLPRI){
LOGD("POLLPRI");
off = lseek(fd, 0, SEEK_SET);
if(off == -1) break;
memset(&buf[0], 0, 11);
read(fd, &buf[0], 10*sizeof(char));
// These two lines will cause it to poll constantly
// close(fd);
// fd = open(path, O_RDONLY);
LOGD("Before callback");
callback(atoi(buf));
LOGD("After Callback");
}
LOGD("for ends");
}
close(fd);
LOGD("for exits");

return 0;
}

最佳答案

在您的代码中,fd 未初始化。

当您打开文件时,您直接分配给gpio_poll_fd.fd,而不使用fd,因此fd保持未初始化。

尝试:

gpio_poll_fd.fd = fd = open(path, O_RDONLY);

正如评论中指出的,根据 GPIO manual (直到更仔细地阅读这些评论后我才阅读),GPIO sysfs 接口(interface)有点特殊:

If the pin can be configured as interrupt-generating interrupt and if it has been configured to generate interrupts (see the description of "edge"), you can poll(2) on that file and poll(2) will return whenever the interrupt was triggered. If you use poll(2), set the events POLLPRI and POLLERR. If you use select(2), set the file descriptor in exceptfds. After poll(2) returns, either lseek(2) to the beginning of the sysfs file and read the new value or close the file and re-open it to read the value.

因此,虽然它不是典型的 poll() 习惯用法,但您的关闭和重新打开结构是正确的。但是,我会选择让文件描述符保持打开状态。因此,这是我将如何构建您的代码:

int read_gpio(char *path, void (*callback)(int)){
char buf[11];
int fd, res, off;
struct pollfd pfd;
if((pfd.fd = fd = open(path, O_RDONLY)) == -1){
perror("path");
return -1;
}
LOGD("First read");
res = read(fd, buf, 10);
assert(res == 10);
LOGD("Before callback");
callback(atoi(buf));
LOGD("After Callback");
pfd.events = POLLPRI|POLLERR; // poll(2) says setting POLLERR is
// unnecessary, but GPIO may be
// special.
for(;;){
LOGD("for begins");
if((res = poll(&pfd,1,-1)) == -1){
perror("poll");
break;
}
LOGD("polling ended");
if((pfd.revents & POLLPRI) == POLLPRI){
LOGD("POLLPRI");
off = lseek(fd, 0, SEEK_SET);
if(off == -1) break;
memset(buf, 0, 11);
res = read(fd, buf, 10);
assert(res == 10);
LOGD("Before callback");
callback(atoi(buf));
LOGD("After Callback");
} else {
// POLLERR, POLLHUP, or POLLNVAL
break;
}
LOGD("for ends");
}
close(fd);
LOGD("for exits");

return 0;
}

关于c - poll() 不阻塞,立即返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37620578/

54 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com