无法从伪终端读取
问题描述:
我写了一个高级包装和命令集合,它使用RProc/RPMsg接口与微处理器进行通信,为了尽可能多地测试我为它编写了单元测试一个Linux伪终端代替'真实'的界面。无法从伪终端读取
我的测试没有奏效。我最终简化了测试,它没有包含我的代码痕迹点 - 它仍然不能正常工作:
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);
}
它的输出是:
*** 1 failure is detected in the test module "cmPTP Test Suite"
# cmPTP-manager-test -l all --run_test=comms_rproc_interface/constructor
Running 1 test case...
Entering test module "cmPTP Test Suite"
interface_test.cpp(17): Entering test suite "comms_rproc_interface"
interface_test.cpp(19): Entering test case "constructor"
interface_test.cpp(23): info: check master_pty != -1 has passed
interface_test.cpp(24): info: check grantpt(master_pty) != -1 has passed
interface_test.cpp(25): info: check unlockpt(master_pty) != -1 has passed
interface_test.cpp(32): info: check slave_pty != -1 has passed
interface_test.cpp(72): info: check in_data.size() == bytes_written has passed
interface_test.cpp(77): error: in "comms_rproc_interface/constructor": check bytes_read == bytes_written has failed [0 != 4]
interface_test.cpp(19): Leaving test case "constructor"; testing time: 15282us
interface_test.cpp(17): Leaving test suite "comms_rproc_interface"; testing time: 15931us
Leaving test module "cmPTP Test Suite"; testing time: 16879us
*** 1 failure is detected in the test module "cmPTP Test Suite"
我可以写我的4字节好,但是从来没有任何东西存在。为什么?
答
这是因为我忘了我正在创建一个伪终端而不是一个串行设备。 PTY正在将我的输入值视为ASCII(可能会使它变得有点吓人),并且在刷新之前正在等待线返回 - 因此@starturtle关于刷新的评论是正确的,而不是以“正常”文件写入方式。
这繁琐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);
}
这看起来并不像读出的实际上是失败了,但它并没有检索字节。写入缓冲区是否已被刷新? – starturtle
@starturtle应该有:“POSIX要求在write()返回后可以证明发生的读(2)返回新数据。注意并非所有的文件系统都符合POSIX标准。”我当然认为Linux/EXT4符合POSIX标准......我如何强制刷新? – cmannett85
@starturtle其实它只是在我身上发现PTS是_two_文件描述符,所以上述不适用。 – cmannett85