У меня однопоточное приложение Linux, использующее boost :: asio для асинхронного ввода/вывода. Теперь мне нужно расширить это приложение для чтения в входах GPIO на /sys/class/gpio/gpioXX/value
.Как использовать boost :: asio с Linux GPIO
Это можно сделать с помощью boost :: asio :: posix :: stream_descriptor по входам GPIO с кратным фронтом?
Я настроил вход 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
всегда вызывает обработчик (конечно, только в пределах io_service.run()
) с EOF или - в случае, если указатель файла был установлен назад - 2 байта данных.
Я не эксперт в области boost::asio
внутренности, но может ли причина быть в том, что реактор epoll boost::asio
запускается на уровне вместо того, чтобы срабатывать в конце в случае 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;
}
["boost использует кроссировочный способ epoll"] (http://lists.boost.org/boost-users/2013/05/78931.php) –
Ну, спасибо за ссылку, но как один может видеть в grep-выходе EPOLLET не используется в любом случае. – Florian
как это «не используется в любом случае»? EPOLLET используется в разных местах. –