管道上的EOF正在打印垃圾

时间:2013-10-15 19:25:36

标签: c operating-system pipe eof

编辑:因此,通过一些额外的调试,EOF成功写入管道(我知道这是因为我测试过以确保write()函数在{{{0}上返回0 1}}。 HOWEVER 读取来自同一个管道时,它说我遇到了EOF(好),但EOF元素的值等于255(而不是-1喜欢它通常是)。有谁知道为什么这是???

我正在尝试编写这个程序,但是当我从stdin遇到EOF时,它并没有写一个-1到管道。无论出于何种原因,当试图通过管道传递EOF时,都会写入垃圾,因此所有后续进程都会被无限循环捕获。

除了在produceStdin函数中打印数组的那些打印语句之外的所有打印语句都是我试图调试它(由于分叉而无法使用调试器)

另外:其中一些评论被回收,所以如果你看到提到一个“缓冲区”,那是因为 这是先前使用缓冲而不是管道编程的。

以下是代码:

printOut()

2 个答案:

答案 0 :(得分:2)

替代传递通过管道读取的2字节版本,因此接收端可以区分char和EOF。

int c = 0;
while(c!=EOF) {
  c = fgetc(stdin);
  short sc = (short) c;
  // `sc` will _typically_ have the values -1 (EOF) and 0,1,2,... 255.
  write(writePipe, &sc, sizeof(sc));
}

int c=0;
int c2=0;
while(c != EOF && c2 != EOF) {
  short sc;          
  if (sizeof(sc) != read(readPipe, &sc, sizeof(sc))) handle_error();
  // `sc` will _typically_ have the values -1 (EOF) and 0,1,2,... 255.
  c = sc;
  ...

原始建议的答案。

c 所有字符被读取之后才会成为EOF 使用:

// while(c!=EOF) {
//   c=fgetc(stdin);
//   write(writePipe, &c, sizeof(char));
// }
while((c = fgetc(stdin)) != EOF) {
  write(writePipe, &c, sizeof(char));
}

应评估read(readPipe, &c, sizeof(char));的返回值,而不是寻找c成为EOF。 EOF不适合char

// int c=0;
// int c2=0;
// while(c!=EOF && c2!=EOF) {
//    read(readPipe, &c, sizeof(char));

char c=0;
char c2=0;
while(1 == read(readPipe, &c, sizeof(char))) {

答案 1 :(得分:0)

这一位在编写代码时存在问题:

int c = 0;

while(c!=EOF)
{
    c=fgetc(stdin);
    write(writePipe, &c, sizeof(char));
}

您应该使用:

int c;

while ((c = fgetc(stdin)) != EOF)
{
    char c1 = c;
    write(writePipe, &c1, sizeof(char));
}

fgetc()的输出是作为int或EOF返回的无符号字符值。实际上,你检测到了EOF,然后写了一个真正不应该写入的管道字节。一般来说,c1的使用是必要的;你可能会忘记你在小端机器上写的内容,但它在大端机器上无法正常工作。您应该检查写入是否成功。

等效的阅读代码有类似的问题。你有:

int c=0;
while(c!=EOF)
{
    read(readPipe,&c,sizeof(char));
    if(c=='\n')
    {
        c=' '; //test for newline
    }
    write(writePipe, &c, sizeof(char));
}

你需要:

char c;
while (read(readPipe, &c, sizeof(char)) == sizeof(char))
{
    if (c == '\n')
        c = ' ';
    write(writePipe, &c, sizeof(char));
}

同样,还有little-endian vs big-endian可移植性问题,以及输入操作的测试(总是,但总是检查输入操作;你经常可以在不检查输入操作的情况下离开输出,但你必须经常检查输入。)

请注意,通过read()write()的单字符I / O对于高性能应用程序而言非常昂贵。标准I / O单字符I / O是正常的,因为它缓冲输入或输出,并且不会调用每次读取和每次写入的系统调用的开销。对于玩具应用程序,您不会注意到开销。

这可能是chux在他answer中所说的,以稍微不同的方式表达。