c++ - 读取命名管道不会刷新它

标签 c++ linux named-pipes

这是我第一次使用 unix 命名管道进行测试。下面是一个简单的示例,它尝试每秒读取给定的管道,并在成功时将“触发”输出到标准输出。使用 bash 脚本,我可以将该值写入程序按预期读取的管道。

问题是,尽管只将值写入管道一次,但程序会在接下来的每个循环中继续读取该值。我能找到的每个教程都告诉我,从管道读取的所有内容基本上都被删除了,如果想要刷新管道,只需阅读所有内容即可。但是下面的程序在没有新输入的情况下一遍又一遍地输出值。

main.cpp

// std
#include <iostream>
// unix
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>


int main(int argc, char* argv[]) {

    // create named pipe
    mkfifo("/tmp/alarm_motion", 0666);

    for(;;){

        int fifo = open("/tmp/alarm_motion", O_RDONLY | O_NONBLOCK);
        char temp[sizeof(int)];
        int st = read(fifo, temp, sizeof(temp));
        if(st == 0){
            int res = atoi(temp);
            std::cout << "fifo" << res;
            if(res == 1){
                std::cout << " -> triggered";
                    close(fifo);
            }
            std::cout << std::endl;
        }
        sleep(1);
    }
}

测试.sh

#!/bin/bash
pipe=/tmp/alarm_motion
echo 1 > $pipe

如果我编译程序,启动它,并在几个周期后执行脚本,我会收到下面的输出

示例输出

fifo0
fifo0
fifo0
fifo0
fifo0
fifo0
fifo1 -> triggered
fifo1 -> triggered
fifo1 -> triggered
fifo1 -> triggered
fifo1 -> triggered
fifo1 -> triggered

虽然我希望得到以下输出

期望的输出

fifo0
fifo0
fifo0
fifo0
fifo0
fifo0
fifo1 -> triggered
fifo0
fifo0
fifo0
fifo0
fifo0

有人能告诉我我做错了什么吗?

Raspbian 8 上的 g++(Raspbian 4.9.2-10)

最佳答案

你的程序有一些严重的缺陷:

  • 文本形式的整数可能比 int 的大小。例如,文本 "12345678"8 字节(不包括字符串终止符!),这应该与 4 的通常大小进行比较 sizeof(int)

  • 没有人说您读取的数据将以零结尾。这意味着所有将您读取的数据视为以零结尾的字符串(例如 atoi)的函数都不会可靠地工作。

  • 当管道被另一端关闭时,read 函数返回0。这意味着您尝试使用的数据并不真正存在。 read 调用(在返回 0 之后)实际上并未读取任何内容。

  • 您有严重的资源泄漏,因为您一遍又一遍地打开管道而不关闭它。

  • 您处理任何事情都没有错误。

最后,您似乎一遍又一遍地读取相同的数据可能是因为编译器如何实现您的 temp 数组。它只是重复使用相同的内存。因为你只是继续一遍又一遍地循环,你会一遍又一遍地看到相同的数据,因为数组的位置是相同的,并且编译器(或你的程序)已经以任何方式清除了两者之间的内存。管道被冲洗,你的内存内容没有。

关于c++ - 读取命名管道不会刷新它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43465927/

相关文章:

c++ - Boost 库、序列化和符号运算符?

c++ - 在 C++ 中运行 CMD 行使用变量(不是字符串文字)作为参数

python - 启动时自动运行 Python 脚本 - Ubuntu 16.04

linux - 音频 channel 自动更改/交换

python - Windows命名管道: detect in Python on writer side when reader has closed its end without having to write data

c++ - 如何使动态字符串在控制台中使用 UTF-8?

c++ - 删除所有左值转换运算符

linux - 清理linux系统

java - 为什么java的RandomAccessFile在linux上不返回?

windows - 如何优雅地停止正在监听 Windows 管道的服务器进程