无法从伪终端读取

时间:2017-05-06 10:34:56

标签: c++ linux terminal boost-test

我编写了一个高级包装器和命令集合,它使用RProc / RPMsg接口与微处理器通信,以便尽可能地测试我为其使用的单元测试一个Linux伪终端代替了真正的'接口

我的测试没有用。我最终将测试简化到了不包含我的代码痕迹的地步 - 它仍然无法工作:

git remote prune origin

其输出为:

BOOST_AUTO_TEST_CASE(constructor)
{
    const auto master_pty = ::posix_openpt(O_RDWR);
    BOOST_REQUIRE(master_pty != -1);
    BOOST_REQUIRE(::grantpt(master_pty) != -1);
    BOOST_REQUIRE(::unlockpt(master_pty) != -1);

    const auto slave_pty_name = ::ptsname(master_pty);
    const auto slave_pty = ::open(slave_pty_name, O_RDWR);
    BOOST_REQUIRE(slave_pty != -1);

    const auto in_data = std::array<std::uint8_t, 4>{1, 2, 3, 4};
    const auto bytes_written = ::write(master_pty, in_data.data(), in_data.size());
    if (bytes_written < 0) {
        BOOST_FAIL("Failed to write: " << errno);
    }
    BOOST_REQUIRE_EQUAL(in_data.size(), bytes_written);

    auto out_data = std::array<std::uint8_t, in_data.size()>{};
    const auto bytes_read = ::read(slave_pty, out_data.data(), out_data.size());
    BOOST_CHECK_EQUAL(bytes_read, bytes_written);
    if (bytes_read < 0) {
        BOOST_FAIL("::read failed: " << errno);
    }

    ::close(slave_pty);
    ::close(master_pty);
}

我可以很好地写出我的4个字节,但是从属端没有任何东西存在。为什么呢?

1 个答案:

答案 0 :(得分:0)

这是因为我忘记了我正在创建一个伪终端而不是一个串行设备。 PTY正在将我的输入值视为ASCII(这可能会让它变得有点吓人),并且在刷新之前正在等待一行返回 - 所以@ starturtle关于刷新的评论是正确的,而不是在&#39;正常&#39;文件写入路。

这个简短的SSCCE展示了我应该如何做到这一点:

#include <unistd.h>
#include <pty.h>

#include <array>
#include <iostream>

int main()
{
    // Make the PTY 'raw' to disable traditional terminal-like
    // behaviour
    struct termios ts;
    cfmakeraw(&ts);

    auto master_pty = -1;
    auto slave_pty  = -1;
    if (::openpty(&master_pty, &slave_pty, nullptr, &ts, nullptr) < 0) {
        std::cerr << "Cannot create PTY: " << errno << std::endl;
        return EXIT_FAILURE;
    }

    const auto in_data = std::array<std::uint8_t, 5>{1, 2, 3, 4, 5};
    const auto bytes_written = ::write(master_pty, in_data.data(), in_data.size());
    if (bytes_written < 0) {
        std::cerr << "Failed to write: " << errno << std::endl;
        return EXIT_FAILURE;
    }

    auto out_data = std::array<std::uint8_t, in_data.size()>{};
    out_data.fill(0);

    const auto bytes_read = ::read(slave_pty, out_data.data(), out_data.size());
    if (bytes_read < 0) {
        std::cerr << "::read failed: " << errno << std::endl;
        return EXIT_FAILURE;
    }

    for (auto&& c : out_data) {
        std::cout << static_cast<int>(c);
    }
    std::cout << std::endl;

    ::close(slave_pty);
    ::close(master_pty);
}