当两个管道属于同一进程时,如何冲洗管道以清理C中的缓冲区? [英] How to flush pipes to clean the buffer in C, when both pipes are part of same process?
问题描述
在X函数中,我正在使用管道缓冲(printfs
的对,这是从X函数内部调用的Y函数打印的)stdout
流,如果有一个Fd,然后在缓冲完成之后,请关闭一个管道和其他Fd,然后在其上使用printf
.
我想完全确定缓冲区为空,下次再次调用此X函数来执行任务时. 我尝试了一些在网上找到的东西:
-
fflush
-
ioctl
,_flushlbf
:看起来gcc不支持它们. g ++支持吗? -
fseek(stdin,EOF,SEEK_END);
-
fpurge(ofp);
我多次调用X()
函数.如果下一组输出大于上一组,则我编写的当前代码可以正常工作.
如果下一组输出小于当前输出组.然后下一组有一些额外的垃圾值,这给了我一个指示,即缓冲区可能尚未完全刷新.
由于某些原因,我已经用C语言编写了完整的代码,但是使用的是g ++编译器.
我的代码如下:
void X(int pairs,char* expOut)
{
char buf[256];
int fds[2];
char output[300];
char input[50];
/* opening pipes */
pipe(fds);
/* saving the the given stdout stream */
int bak = dup(STDOUT_FILENO);
/* associating Fds[1] pipe with stdout */
int res=dup2(fds[1],STDOUT_FILENO);
/* associating Fds[0] pipe with stdin */
dup2(fds[0],STDIN_FILENO);
assert(res!=-1);
/* Call To function Y: function combParenthesis is a recursive function,
which prints out some strings couple of time */
combParenthesis(pairs) ;
fflush(stdout);
/* closing stdout FD stream */
close(fds[1]);
fflush(stdout);
/* restoring the old stdout stream */
dup2(bak, 1);
close(bak);
/* opening, stdin stream for reading */
FILE *ofp = fdopen(fds[0], "r");
char strs[30][30];
for (int i=0;i<30;i++) {
memset(strs[i], 0, 30);
}
int i=0;
if (ofp)
{
int sz;
if((pairs*2)+1 <= 1)
{
sz=5;
}
else
{sz = (pairs*2)+1 ;}
/* read the stream line by line */
while (fgets(buf,sz ,ofp)) {
printf("\n next string %s", buf);
i++;
}
if (ferror(ofp)) {
printf("something went wrong in the input to printf");
}
}
/* different ways to flush it out */
char c;
while( (c = fgetc( ofp )) != EOF && c != '\n' );
fseek(stdin,EOF,SEEK_END);
fpurge(ofp);
fclose(ofp);
fflush(stdin);
// _flushlbf();
/* close the fd associated with stdin */
close(fds[0]);
}
fflush
定位末尾的精度.
我设法使用自己的combParenthesis
来运行您的代码(第一遍:中等字符串,第二遍:较大的字符串,第三个较小的字符串).我从未在输出中发现垃圾...只要用stderr
printf("\n next string %s", buf);
fprintf(stderr, "\n next string %s", buf);
我也通过在stdin和ofp之后用单个fflush(stdout)
刷新stdout来获得正确的输出.恕我直言,问题是:
- 关闭管道,以便不再将stdout复制到ofp或stdin
- 您使用
printf("\n next string %s", buf)
在stdout上进行写操作,并且stdout可能会被缓冲 - 您刷新已经干净的流
- 当您在下次通话中重复stdout时,您可能会阅读stdout中最后一次传递的内容
这是我发现的主要改进:
- 如果使用管道 duping stdout读取的
combParenthesis
输出,切勿在任何地方写入stdout(或确保将其刷新) - 您做了不必要的
dup2(fds[0],STDIN_FILENO);
,因为您直接在管道的另一端阅读(更好) - 您永远不会验证
sz = (pairs*2)+1
小于sizeof(buf)
实际上,我已经意识到,即使在将复制到fds [1]之前刷新stdout,即使在应用程序中其他位置混用 因此,这是 我从不对读取的内容进行垃圾处理,即使将输出重定向到文件也可以正常工作,但是由于我无法解释的原因,消息的顺序不是我期望的.希望这对您来说无关紧要 In a X function, I am using pipes, to buffer(couple of I want to be completely sure that buffer is empty, when next time this X function is called again to do the task.
I tried couple of things which I found online: I call If next set of output is less the present set of output. Then next set have some extra garbage values, which gives me an indication , that buffer may have not flushed completely. Because of certain reason, I have written entire code in C but using g++ compiler. My code as follows:
EDIT: a precision at the end on I managed to run your code simply using a I also got correct output by flushing stdout after stdin and ofp by a single Here are the main improvements that I found : Edit : In fact, I have just realized that your code could work, even with intermixed So here is a fixed version of your I never got garbage in what is read and it works even with output redirected to a file, but for a reason I couldn't explain, the order of the messages is not what I would expect. Hope it's not a concern for you 这篇关于当两个管道属于同一进程时,如何冲洗管道以清理C中的缓冲区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!printf
,您的代码也可以工作. /p>
X()
函数的固定版本,带有明确标识的修改(但恕我直言,您也应该考虑我的其他建议):void X(int pairs,char* expOut)
{
char buf[256];
int fds[2];
char output[300];
char input[50];
/* BEGIN EDIT */
/* first flush stdout */
fflush(stdout);
/* END EDIT */
/* opening pipes */
pipe(fds);
/* saving the the given stdout stream */
int bak = dup(STDOUT_FILENO);
/* associating Fds[1] pipe with stdout */
int res=dup2(fds[1],STDOUT_FILENO);
/* associating Fds[0] pipe with stdin */
dup2(fds[0],STDIN_FILENO);
assert(res!=-1);
/* Call To function Y: function combParenthesis is a recursive function,
which prints out some strings couple of time */
combParenthesis(pairs) ;
/* closing stdout FD stream */
close(fds[1]);
fflush(stdout);
/* restoring the old stdout stream */
dup2(bak, 1);
close(bak);
/* opening, stdin stream for reading */
FILE *ofp = fdopen(fds[0], "r");
char strs[30][30];
for (int i=0;i<30;i++) {
memset(strs[i], 0, 30);
}
int i=0;
if (ofp)
{
int sz;
if((pairs*2)+1 <= 1)
{
sz=5;
}
else
{sz = (pairs*2)+1 ;}
/* read the stream line by line */
// EDIT : changed sz with sizeof(buf)-1 - cause: no correct pairs value
while (fgets(buf, sizeof(buf) - 1,ofp)) {
printf("\n next string %s", buf);
i++;
}
if (ferror(ofp)) {
printf("something went wrong in the input to printf");
}
}
/* different ways to flush it out */
/* BEGIN EDIT : ALL FLUSHING COMMENTED OUT
char c;
while( (c = fgetc( ofp )) != EOF && c != '\n' );
fseek(stdin,EOF,SEEK_END);
fpurge(ofp);
fclose(ofp);
fflush(stdin);
// _flushlbf();
END EDIT */
/* close the fd associated with stdin */
close(fds[0]);
}
printfs
, which are printed in Y function called inside from X function) the stdout
stream if one Fd and then after buffer is complete,close one pipe and other Fd and then use printf
on it.
fflush
ioctl
, _flushlbf
: looks like they aren't supported by gcc. Does g++ support it?fseek(stdin,EOF,SEEK_END);
fpurge(ofp);
X()
function, couple of times. The present code, I have written, works fine if next set of output is greater than previous set.void X(int pairs,char* expOut)
{
char buf[256];
int fds[2];
char output[300];
char input[50];
/* opening pipes */
pipe(fds);
/* saving the the given stdout stream */
int bak = dup(STDOUT_FILENO);
/* associating Fds[1] pipe with stdout */
int res=dup2(fds[1],STDOUT_FILENO);
/* associating Fds[0] pipe with stdin */
dup2(fds[0],STDIN_FILENO);
assert(res!=-1);
/* Call To function Y: function combParenthesis is a recursive function,
which prints out some strings couple of time */
combParenthesis(pairs) ;
fflush(stdout);
/* closing stdout FD stream */
close(fds[1]);
fflush(stdout);
/* restoring the old stdout stream */
dup2(bak, 1);
close(bak);
/* opening, stdin stream for reading */
FILE *ofp = fdopen(fds[0], "r");
char strs[30][30];
for (int i=0;i<30;i++) {
memset(strs[i], 0, 30);
}
int i=0;
if (ofp)
{
int sz;
if((pairs*2)+1 <= 1)
{
sz=5;
}
else
{sz = (pairs*2)+1 ;}
/* read the stream line by line */
while (fgets(buf,sz ,ofp)) {
printf("\n next string %s", buf);
i++;
}
if (ferror(ofp)) {
printf("something went wrong in the input to printf");
}
}
/* different ways to flush it out */
char c;
while( (c = fgetc( ofp )) != EOF && c != '\n' );
fseek(stdin,EOF,SEEK_END);
fpurge(ofp);
fclose(ofp);
fflush(stdin);
// _flushlbf();
/* close the fd associated with stdin */
close(fds[0]);
}
fflush
positioning.combParenthesis
of my own (first pass : medium strings, second : larger strings, third smaller). I never found garbage in output ... as soon as I have replaced your printf("\n next string %s", buf);
by an output on stderr
fprintf(stderr, "\n next string %s", buf);
fflush(stdout)
. IMHO the problem was :
printf("\n next string %s", buf)
and stdout may be buffered
combParenthesis
with a pipe duping stdout, never write to stdout in any over place (or be sure to flush it)dup2(fds[0],STDIN_FILENO);
because you directly read on the other end of the pipe (which is better)sz = (pairs*2)+1
is smaller than sizeof(buf)
printf
elsewhere in the application, provided you flush stdout before copying it to fds[1].X()
function with clearly identified edits (but IMHO you should considered my other suggestions too) : void X(int pairs,char* expOut)
{
char buf[256];
int fds[2];
char output[300];
char input[50];
/* BEGIN EDIT */
/* first flush stdout */
fflush(stdout);
/* END EDIT */
/* opening pipes */
pipe(fds);
/* saving the the given stdout stream */
int bak = dup(STDOUT_FILENO);
/* associating Fds[1] pipe with stdout */
int res=dup2(fds[1],STDOUT_FILENO);
/* associating Fds[0] pipe with stdin */
dup2(fds[0],STDIN_FILENO);
assert(res!=-1);
/* Call To function Y: function combParenthesis is a recursive function,
which prints out some strings couple of time */
combParenthesis(pairs) ;
/* closing stdout FD stream */
close(fds[1]);
fflush(stdout);
/* restoring the old stdout stream */
dup2(bak, 1);
close(bak);
/* opening, stdin stream for reading */
FILE *ofp = fdopen(fds[0], "r");
char strs[30][30];
for (int i=0;i<30;i++) {
memset(strs[i], 0, 30);
}
int i=0;
if (ofp)
{
int sz;
if((pairs*2)+1 <= 1)
{
sz=5;
}
else
{sz = (pairs*2)+1 ;}
/* read the stream line by line */
// EDIT : changed sz with sizeof(buf)-1 - cause: no correct pairs value
while (fgets(buf, sizeof(buf) - 1,ofp)) {
printf("\n next string %s", buf);
i++;
}
if (ferror(ofp)) {
printf("something went wrong in the input to printf");
}
}
/* different ways to flush it out */
/* BEGIN EDIT : ALL FLUSHING COMMENTED OUT
char c;
while( (c = fgetc( ofp )) != EOF && c != '\n' );
fseek(stdin,EOF,SEEK_END);
fpurge(ofp);
fclose(ofp);
fflush(stdin);
// _flushlbf();
END EDIT */
/* close the fd associated with stdin */
close(fds[0]);
}