【发布时间】:2020-11-21 18:38:38
【问题描述】:
我在 C++ 程序中有一个线程,专门用于读取通过等待用户输入的 bash 脚本写入的命名管道。我希望 ReadFromPipe() 每次通过管道发送时都会阻塞并对用户输入做出反应。
read() 在这段代码 sn-p 中没有阻止我,我不确定为什么。
重击:
# create pipe
write_pipe=/tmp/bash_to_c
if [[ ! -p $write_pipe ]]; then
mkfifo $write_pipe
fi
USER_INPUT=""
while true; do
read USER_INPUT
echo $USER_INPUT > $write_pipe
done
C++:
std::string ReadFromPipe()
{
char buffer[500];
int fd;
std::string pipe = "./tmp/bash_to_c";
fd = open(pipe.c_str(), O_RDONLY);
read(fd, buffer, 500);
buffer[strcspn(buffer, "\n")] = 0;
buffer[strlen(buffer)] = '\0';
close(fd);
return std::string(buffer);
}
void* pipeCommunicationThreadFunc(void *args)
{
bool continueReadingFromPipe = true;
while(continueReadingFromPipe)
{
// read from pipe
std::string message = ReadFromPipe();
std::cout << "message: " << message << std::endl;
}
}
【问题讨论】:
-
打印什么吗?
-
“不阻塞”是指它从不等待并返回一个空字符串吗?还是等待然后返回部分字符串?
-
您没有检查打开管道是否真的成功 - 文件名
"./tmp/bash_to_c"看起来不对。您创建的是"/tmp/bash_to_c"而不是"./tmp/bash_to_c",所以除非您从/启动程序,否则它将失败。执行cd /,然后键入 C++ 程序的路径以运行它。那它就可以工作了。 -
如果它读取的字符串没有换行符,就会发生各种不好的事情......你需要使用
read()的返回值而不是忽略它。使用std::ifstream更容易读取它,因此您不必实现自己的基于行的缓冲。 -
buffer[strlen(buffer)] = '\0';是一种反模式。strlen搜索预先存在的 NUL 终止符,因此如果没有,则此语句不会添加一个,但会导致未定义的行为。去掉这条线,没有意义。确保以其他方式存在 NUL。更好的是,如果可能,切换到 C++ 字符串。