C++ 管道数据以块的形式打印出来
C++ Piped data prints out in blocks
我正在尝试编写一个程序,该程序将另一个程序的 stdout
拆分成行并打印出来。
这个其他程序不停地输出数据(大约每秒 800 个字符)。
我已经分叉它并使用 dup2 将其 stdout
发送到父进程的管道。
问题是父进程读取了数据,但它只能每 6 秒以大约 150 行的块打印出来。
所以它打印数据,然后 6 秒什么都不打印,然后更多数据,然后什么都不打印....一遍又一遍
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
int pipe1[2];
char readbuf[5];
string line = ">>";
if (pipe(pipe1) != 0){ //Setting up the pipe
cerr << "Pipe failed\n"; exit(1);
}
pid_t pid = fork(); //Setting up the fork
if (pid < 0){
cerr << "Fork failed\n" ;exit(-1);
}
else if (pid == 0){
//Child Process
dup2(pipe1[1], STDOUT_FILENO); //dup2()ing stdout to pipe
close(pipe1[1]); //closing other pipe connections
close(pipe1[0]);
execl("program_folder/program", "program_folder/program", NULL); //running the program
}
else{
//Parent
close(pipe1[1]); //closing write end of pipe
for (;;){
do{
if (read(pipe1[0], readbuf, 1) < 0){
cout << "read error"<<endl;
return 1;
} //Reads 1 character at a time,
line.push_back(readbuf[0]); //pushing them onto a string,
}while(readbuf[0] != '\n'); //until the new line character is reached
cout<< line; //Prints the line of data
line= ">>";
}
close(pipe1[0]);
}
return 0;
}
输出如下所示:(偏航、俯仰、滚动值)
>>ypr 63.71 -68.52 19.24
>>ypr 63.75 -68.52 19.24
>>ypr 63.78 -68.52 19.24
>>ypr 63.81 -68.52 19.24
>>ypr 63.85 -68.52 19.24
>>ypr 63.89 -68.52 19.23
>>ypr 63.93 -68.52 19.24
>>ypr 63.97 -68.52 19.24
>>ypr 64.00 -68.52 19.24
将来我想通过套接字将这些发送到另一台计算机并实时绘制它们,使用 gnuplot 之类的东西。我知道使用 python 会更容易,但我只是想尝试使用 C.
我试过使用 std::endl;和 std::cout.flush();但运气不好。
我做错了什么?
当您使用管道时,数据流中不再有一行一行的输出。这是一个普遍的 UNIX 问题。 stdout 检查输出流是否为 tty(通过调用 isatty(3)
),因此它会在输出中找到每个 \n
时刷新输出,或者当 BUFSIZ
字符填满缓冲区时刷新输出。由于您的程序中有 pipe(2)
d,因此不再有行缓冲,因此缓冲区在块块处被刷新。您可以通过在适当的位置插入对 fflush(stdout);
的调用(C 语言)来强制刷新。或者正如在评论(感谢@spectras)中指出的那样,使用以下行(仅适用于 C++):
cout << "your line here" << std::flush;
(您必须编辑管道写入器,因为您无法控制写入器缓冲区如何从 reader 进程运行。)
我正在尝试编写一个程序,该程序将另一个程序的 stdout
拆分成行并打印出来。
这个其他程序不停地输出数据(大约每秒 800 个字符)。
我已经分叉它并使用 dup2 将其 stdout
发送到父进程的管道。
问题是父进程读取了数据,但它只能每 6 秒以大约 150 行的块打印出来。
所以它打印数据,然后 6 秒什么都不打印,然后更多数据,然后什么都不打印....一遍又一遍
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
int pipe1[2];
char readbuf[5];
string line = ">>";
if (pipe(pipe1) != 0){ //Setting up the pipe
cerr << "Pipe failed\n"; exit(1);
}
pid_t pid = fork(); //Setting up the fork
if (pid < 0){
cerr << "Fork failed\n" ;exit(-1);
}
else if (pid == 0){
//Child Process
dup2(pipe1[1], STDOUT_FILENO); //dup2()ing stdout to pipe
close(pipe1[1]); //closing other pipe connections
close(pipe1[0]);
execl("program_folder/program", "program_folder/program", NULL); //running the program
}
else{
//Parent
close(pipe1[1]); //closing write end of pipe
for (;;){
do{
if (read(pipe1[0], readbuf, 1) < 0){
cout << "read error"<<endl;
return 1;
} //Reads 1 character at a time,
line.push_back(readbuf[0]); //pushing them onto a string,
}while(readbuf[0] != '\n'); //until the new line character is reached
cout<< line; //Prints the line of data
line= ">>";
}
close(pipe1[0]);
}
return 0;
}
输出如下所示:(偏航、俯仰、滚动值)
>>ypr 63.71 -68.52 19.24
>>ypr 63.75 -68.52 19.24
>>ypr 63.78 -68.52 19.24
>>ypr 63.81 -68.52 19.24
>>ypr 63.85 -68.52 19.24
>>ypr 63.89 -68.52 19.23
>>ypr 63.93 -68.52 19.24
>>ypr 63.97 -68.52 19.24
>>ypr 64.00 -68.52 19.24
将来我想通过套接字将这些发送到另一台计算机并实时绘制它们,使用 gnuplot 之类的东西。我知道使用 python 会更容易,但我只是想尝试使用 C.
我试过使用 std::endl;和 std::cout.flush();但运气不好。
我做错了什么?
当您使用管道时,数据流中不再有一行一行的输出。这是一个普遍的 UNIX 问题。 stdout 检查输出流是否为 tty(通过调用 isatty(3)
),因此它会在输出中找到每个 \n
时刷新输出,或者当 BUFSIZ
字符填满缓冲区时刷新输出。由于您的程序中有 pipe(2)
d,因此不再有行缓冲,因此缓冲区在块块处被刷新。您可以通过在适当的位置插入对 fflush(stdout);
的调用(C 语言)来强制刷新。或者正如在评论(感谢@spectras)中指出的那样,使用以下行(仅适用于 C++):
cout << "your line here" << std::flush;
(您必须编辑管道写入器,因为您无法控制写入器缓冲区如何从 reader 进程运行。)