【发布时间】:2015-08-08 03:39:20
【问题描述】:
我有一个使用 boost::asio 进行异步输入/输出的单线程 Linux 应用程序。现在我需要扩展这个应用程序以读取/sys/class/gpio/gpioXX/value 上的 GPIO 输入。
可以在边沿触发的 GPIO 输入上使用 boost::asio::posix::stream_descriptor 吗?
我将 GPIO 输入配置如下:
echo XX >/sys/class/gpio/export
echo in >/sys/class/gpio/gpioXX/direction
echo both >/sys/class/gpio/gpioXX/edge
我设法编写了一个基于 epoll 的测试应用程序,该应用程序会阻塞 GPIO 文件描述符,直到 GPIO 信号发生变化,但 boost::asio 似乎无法正确阻塞。对 boost::asio::async_read 的调用总是立即使用 EOF 调用处理程序(当然只在 io_service.run() 内),或者 - 如果文件指针被设置回 - 2 字节数据。
我不是boost::asio 内部的专家,但原因可能是boost::asio epoll 反应器是水平触发的,而不是posix::stream_descriptor 的边缘触发?
这是我的代码:
#include <fcntl.h>
#include <algorithm>
#include <iterator>
#include <stdexcept>
#include <boost/asio.hpp>
boost::asio::io_service io_service;
boost::asio::posix::stream_descriptor sd(io_service);
boost::asio::streambuf streambuf;
void read_handler(const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (error.value() == boost::asio::error::eof) {
// If we don't reset the file pointer we only get EOFs
lseek(sd.native_handle(), 0, SEEK_SET);
} else if (error)
throw std::runtime_error(std::string("Error ") + std::to_string(error.value()) + " occurred (" + error.message() + ")");
std::copy_n(std::istreambuf_iterator<char>(&streambuf), bytes_transferred, std::ostreambuf_iterator<char>(std::cout));
streambuf.consume(bytes_transferred);
boost::asio::async_read(sd, streambuf, &read_handler);
}
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
int fd = open(argv[1], O_RDONLY);
if (fd < 1)
return 1;
try {
sd.assign(fd);
boost::asio::async_read(sd, streambuf, &read_handler);
io_service.run();
} catch (...) {
close(fd);
return 1;
}
close(fd);
return 0;
}
【问题讨论】:
-
好吧,谢谢你的链接,但正如在 grep 输出中看到的那样,EPOLLET 在任何情况下都没有使用。
-
如何“在任何情况下都不使用”? EPOLLET在各个地方都有使用。
-
抱歉,任何 -> 每个 ;)
标签: c++ boost-asio gpio epoll