0

我正在尝试从文件中读取,将其写入管道,然后在子进程中从管道中读取并将其写入新文件。程序传递了两个参数:输入文件的名称和要复制到的文件的名称。这是一个家庭作业项目,但我在网上花了几个小时,并且只找到了让它变得更加混乱的方法。我们得到了两个任务,这个和矩阵乘法与线程。我得到了矩阵乘法没有问题,但是这个应该相当容易,我遇到了很多麻烦。我得到了我正在复制的文件的第一个单词,但随后出现了一大堆乱码。

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

int main(int argc, char *argv[]) {

    if(argc < 3) {
        printf("Not enough arguments: FileCopy input.txt copy.txt\n");
        exit(0);
    }
    char buffer[200];

    pid_t pid;
    int fds[2];

    pipe(fds);
    pid = fork();


    if (pid == 0) { /* The child process */
        //wait(NULL);
        write(1, "hi i am in child\n", 17);
        int copy = open(argv[2], O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP);
        FILE* stream;
        close(fds[1]);

        stream = fdopen(fds[0], "r");
        while (fgets(buffer, sizeof(buffer), stream) != NULL) {
            //printf("%s\n", buffer);
            write(copy, buffer, 200);
            //printf("kjlkjljljlkj\n");
            //puts(buffer);

        }

        close(copy);
        close(fds[0]);

        exit(0);

    }
    else {
        write(1, "hi i am in parent\n", 18);
        FILE* input = fopen(argv[1], "r");
        FILE* stream;
        close(fds[0]);
        stream = fdopen(fds[1], "w");
        /*while (fscanf(input, "%s", buffer) != EOF) {
            //printf("%s\n", buffer);
            fprintf(stream, "%s\n", buffer);
            fflush(stream);
            //printf("howdy doody\n");
        }*/
        fgets(buffer, sizeof(buffer), input);
        printf("%s", buffer);
        fprintf(stream, "%s", buffer);
        fflush(stream);
        close(fds[1]);
        fclose(input);
        wait(NULL);
        exit(0);
    }
    return 0;
}

我做错了读写吗?

4

2 回答 2

2

我做错了读写吗?

是的。

在孩子中,您将面向字符串的缓冲 I/O (fgets()) 与面向块的二进制 I/O 混合在一起。(即 write()。)这两种方法都可以,但通常的做法是选择其中一种。

如果将它们混合在一起,则必须考虑问题的更多方面。例如,在孩子中,您只从管道中读取一行,但随后将整个缓冲区写入文件。这是您可能在文件中看到的乱码的来源。

在父级中,您只发送没有循环的单行。之后,在 fclose() 缓冲 I/O 系统之前关闭底层文件描述符。这意味着当 fclose 尝试刷新缓冲区时,现在关闭的描述符将无法写入任何剩余的数据。

您可以使用 write()/read()/close(),它们是 Posix 指定的内核级操作,也可以使用 fdopen/puts/gets/fclose,它们是 ISO C 指定的标准 I/O 库操作。现在,有一种混合它们的方法会起作用。如果您在父级中使用 stdio,您仍然可以在子级中使用读/写,但是您将为每一行进行内核调用,这通常不是理想的做法。

于 2013-02-20T15:30:48.507 回答
1

您通常应该只使用读/写调用来读/写管道。

您应该为子(只读)和父(只写)关闭管道的相应端。然后,使用 write()-systemcall 从父级写入管道。并在孩子使用 read()-systemcall 阅读。

在这里寻找一个很好的解释。

于 2013-02-20T15:33:05.910 回答