读取整个管道 - c

Read an entire pipe - c

我在使用这段代码时遇到了一些困难。 我需要从管道末端获取所有信息。 但是,我收到段错误。

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int main(void){

    int tube[2];

    if(pipe(tube) == -1){
        perror("Erreur");
        exit(1);
    }

    dup2(tube[1],1);

    printf("Few lines \n");
    printf("of an undefined size. \n");

    while (!feof(tube[0])) {
        char temp = fgetc(tube[0]);
        printf("chaine : %c\n", temp);
    }

    return 0;
}

如果您知道我如何处理这个问题,请解释一下。

您使用的函数 returns 单个字符 (fgetc) 然后将该值视为指向 printf 调用中的字符串的指针。您还将该字符存储为指向字符的指针的地址而不是实际字符,因此当 printf 读取您的字符串时,它正在读取一些它不拥有的低内存。 fgetc returns 字符本身,你需要一个 char 变量,而不是 char*.

尝试:

while (!feof(tube[0])) {
    char temp = fgetc(tube[0]);
    printf("chaine : %c\n", temp);
}

pipe 函数 returns 是一对 int 文件描述符,而不是 FILE 对。这意味着您可以对它们使用 readwriteclose,但不能使用 fgetcfeof.

此外,while(!feof(file))(几乎)总是 wrong,因为在 不成功的读取到达文件末尾后 设置了标志.

这还不是全部。当写入端的所有描述符都关闭时,您只会在管道的读取端获得 EOF。所以你必须关闭或刷新 stdout 以确保所有字符都已写入管道,如果你没有关闭 stdout 则关闭文件描述符 1,并关闭 tube[1] 这仍然是文件描述符的写完管子。

因此您可以将 while 循环替换为:

close(tube[1]);
fclose(stdout);

while (1) {
    char temp;
    if (read(tube[0], &temp, 1) < 1) break;
    fprintf(stderr, "chaine : %c\n", temp);
}

它修复了由于在非 FILE 上使用 feoffgetc 导致的 SEGFAULT,并确保在读取文件之前正确关闭文件的写入端content 以获得良好的文件结束条件。

但是,我收到段错误。 ? 这意味着您没有正确阅读编译器警告。当你做 feof(tube[0]) 它说 feof() 期望 FILE* 但你提供了 int(tube[0] is inetger) type.

/usr/include/stdio.h:828:12: note: expected ‘struct FILE *’ but argument is of type ‘int’

所以第一件事总是阅读编译器警告并使用 -Wall 标志编译代码。

这个fgetc(tube[0]);不是从file descriptor读取数据的方式,使用read()系统调用从文件描述符读取数据不是fgetc()fgetc() 如果您使用 fopen() 打开文件,则可以使用。

还有

dup2(tube[1],1); /* this is not expected one which you want*/

这样使用

dup2(1,tube[1]);/*stdout get duplicated with tube[1] i.e whatever you
                        write on stdout will be written into write end of pipe*/

这是一个简单的例子。

char temp[100];
        int ret = 0;
        ret = read(tube[0],temp,sizeof(temp));/*reading from pipe*/
        if(ret == -1)   {
                perror("read");
                return 0;
        }
        else {
                temp[ret] = '[=12=]';/*read returns no of items read, so put null
                                        at last otherwise you may get some junk data  */
                printf("%s",temp);
        }

阅读 man 2 read & man 2 dup2 了解这些系统调用的工作原理..