我有以下使用 select 的代码:
fd_set fdsu;
FD_ZERO(&fdsu);
FD_SET(fd, &fdsu);
fd_set efds = fdsu;
fd_set dfds = fdsu;
while (1) {
select(cameraUSBP.fd + 1, NULL, &dfds, &efds, NULL);
if (FD_ISSET(cameraUSBP.fd, &efds)) {
errorData();
}
if (FD_ISSET(cameraUSBP.fd, &dfds)) {
writeData();
}
}
我想将其移植以使用 poll:
struct pollfd pollfds[1];
pollfds[0].fd = fd;
pollfds[0].events = POLLIN;
while (1) {
poll(pollfds, 1, -1);
//how to insert writeData() and errorData()
}
我很困惑。如何插入 writeData 和 errorData 事件?
首先,您的
select()
版本有许多重大错误。
来自 linux 手册页:
你没有这样做。您也无法像您正在做的那样可移植地分配请注意:返回后,每个文件描述符集都会被修改以指示哪些文件描述符当前“就绪”。因此,如果在循环中使用
,则在每次调用之前必须重新初始化集合。select()
fd_set
;它适用于某些实现,但不适用于其他实现(例如,如果它是作为数组实现的)。您也不会检查
select()
是否失败。它应该看起来像
while (1) {
fd_set efds, dfds;
FD_ZERO(&efds);
FD_SET(cameraUSBP.fd, &efds);
FD_ZERO(&dfds);
FD_SET(cameraUSBP.fd, &dfds);
if (select(cameraUSBP.fd + 1, NULL, &dfds, &efds, NULL) < 0) {
reportError(errno);
break; // or exit or whatever
}
if (FD_ISSET(cameraUSBP.fd, &efds)) {
errorData();
}
if (FD_ISSET(cameraUSBP.fd, &dfds)) {
writeData();
}
}
另一方面,
struct pollfd
对于要监视的事件和发生的事件有单独的字段,因此如果您正在监视的描述符从不更改,则只需初始化一次。您使用按位或标志将
events
设置为您感兴趣的内容,然后检查
revents
以查看通过按位和相关标志执行操作时发生了什么。
struct pollfd pollfds[1];
pollfds[0].fd = cameraUSBP.fd;
pollfds[0].events = POLLOUT; // since you want to know when it's writable
while (1) {
if (poll(pollfds, 1, -1) < 0) {
reportError(errno);
break;
}
if (pollfds[0].revents & POLLERR) { // Doesn't need to be set in events
errorData();
}
if (pollfds[0].revents & POLLOUT) {
writeData();
}
}