【发布时间】:2016-06-03 17:46:53
【问题描述】:
我正在尝试使用poll() 通过sysfs 捕获GPIO 上的中断。我在第三个位置有-1,所以它可以阻止,但它似乎总是返回。我已经在 SO 上查看了一些类似的帖子。尤其是this (1)、this (2) 和this (3)。
在 (1) 中,通过在调用 poll() 之前放置一个虚拟 read() 来解决此问题。如果我这样做(请参阅代码中注释的read())。我的代码在循环中运行一次,第二次在poll() 上永远阻塞。
在 (2) 中,这可能是一种解释,但并不能真正解决我的问题。
在 (3) 中,我的 read() 之前已经有一个 lseek()
当 gpio 的 value 发生变化时,我怎样才能让这个 poll() 阻塞并仅在中断中返回?
这里是sn-p的代码:
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;
}
【问题讨论】:
-
您的
open()确定成功了吗?您似乎打算测试的代码正在查看错误的变量。 -
@JohnBollinger 当然,我得到了正确的价值。感谢您对测试的提醒。
-
不清楚为什么您认为参考文献 (1) 中给出的答案可以忽略。它似乎解释了您报告的案例的行为,您在打开文件和轮询文件之间没有读取文件。也许您真的想问为什么
poll()在初始读取后执行时会无限期阻塞? -
@JohnBollinger 我没有忽略它,而是尝试在这里使用他们的解决方案。我尝试实施对他们有用的解决方案(请参阅注释掉的
read()以了解我放置虚拟读取的位置)。因此,虽然 (1) 解释了这种行为,但该解决方案在我的实现中并没有奏效。也许我做错了什么,但我不确定是什么。 -
既然代码在你使用dummy read的时候可以工作一次,你有没有考虑过那个版本的代码是ok的?您确定文件在第一次通过后发生更改而不会导致
poll()返回吗?
标签: c linux blocking polling sysfs