C语言 带有文件fread & fwrite管道将文件从一个进程发送到另一个进程

ctehm74n  于 2022-12-11  发布在  其他
关注(0)|答案(1)|浏览(128)

I实现了一个管道,用于从一个100 MB的进程数据文件“传输”到另一个进程。
从一个过程到另一个过程的整个发送工作得很好,但它需要很长的时间...大约2. 5+分钟。
我想将我的函数更改为fread&fwrite,以使函数更快,而阅读每次读取一个字符。我如何使用pd[0] & pd[1]进行此操作,但我几乎不明白如何更改它
任何帮助都将不胜感激!
以下是我的代码:

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

int main() {
    int fd[2];
    pid_t childpid;
    char readbuffer[65535];

    pipe(fd);

    if ((childpid = fork()) == -1) {
        perror("fork");
        exit(1);
    }

    if (childpid == 0) {
        /* Child process closes up input side of pipe */
        close(fd[0]);

        /* Send "string" through the output side of pipe */
        FILE *fp2 = fopen("data.txt", "rb");

        if (fp2 == NULL) {
            //handle error here
            return -1;
        }
        int c;
        while ((c = getc(fp2)) != EOF) {
            if ((write(fd[1], &c, 1)) < 1) {
                fprintf(stderr, "Write to pipe failed.\n");
                perror("write");
                exit(EXIT_FAILURE);
            }
        }
    } else {
        /* Parent process closes up output side of pipe */
        close(fd[1]);

        /* Read in a string from the pipe */
        char *new_data = "new_data.txt";
        FILE *fp = fopen(new_data, "wb");
        ssize_t num_bytes;
        while (num_bytes = (read(fd[0], readbuffer, sizeof(readbuffer))) > 0) {
            fwrite(readbuffer, 1, num_bytes, fp);
            memset(readbuffer, 0, 65535);
        }
        fclose(fp);
    }
    return 0;
}

第2轮已编辑:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
    int fd[2];
    pid_t childpid;
    char readbuffer[1024];

    pipe(fd);

    if ((childpid = fork()) == -1) {
        perror("fork");
        exit(1);
    }

    if (childpid == 0) {
        /* Child process closes up input side of pipe */
        close(fd[0]);

        /* Send "string" through the output side of pipe */
        FILE *fp2 = fopen("data.txt", "rb");

        if (fp2 == NULL) {
            //handle error here
            return -1;
        }
        int c;
//        while ((c = getc(fp2)) != EOF) {
//            if ((write(fd[1], &c, 1)) < 1) {
//                fprintf(stderr, "Write to pipe failed.\n");
//                perror("write");
//                exit(EXIT_FAILURE);
//            }
//        }
        ssize_t num_bytes;
        while ((num_bytes = fread(readbuffer, sizeof(readbuffer), 1024,fp2)) > 0) {
            fwrite(readbuffer, 1, num_bytes, fd[1]);
            //memset(readbuffer, 0, 65535);
        }
    } else {
        /* Parent process closes up output side of pipe */
        close(fd[1]);

        /* Read in a string from the pipe */
        char *new_data = "new_data.txt";
        FILE *fp = fopen(new_data, "wb");
        ssize_t num_bytes;
        while ((num_bytes = read(fd[0], readbuffer, sizeof(readbuffer))) > 0) {
            fwrite(readbuffer, 1, num_bytes, fp);
            //memset(readbuffer, 0, 65535);
        }
        fclose(fp);
    }
    return 0;
}
xam8gpfp

xam8gpfp1#

几个问题...
在您的原始代码中,主要问题[速度方面]是使用长度为1的readwrite
此外,尽管流可以补偿fgetc的位,但它仍然是一次一个字节。
我提出的解决方案是实施William Pursell的建议:使用fdopen将stdio流(即FILE *)附加到管道。
我们可以为父母和孩子都这样做。
然后,只需在两个进程中的fread/fwrite上循环即可。
注意,父和应该执行fclose
并且,父进程应该等待子进程完成(例如waitpid)。
下面是修改后的代码:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>

#ifdef DEBUG
#define dbgprt(_fmt...) \
    do { \
        int sverr = errno; \
        fprintf(stderr,_fmt); \
        errno = sverr; \
    } while (0)
#else
#define dbgprt(_fmt...) \
    do { } while (0)
#endif

int
main(void)
{
    int fd[2];
    FILE *fpinp;
    FILE *fpout;
    pid_t childpid;
    int status;
    ssize_t rlen;
    ssize_t wlen;
#if 0
    char buffer[65535];
#else
    char buffer[1024];
#endif

    setlinebuf(stdout);
    setlinebuf(stderr);

    pipe(fd);

    if ((childpid = fork()) == -1) {
        perror("fork");
        exit(1);
    }

    if (childpid == 0) {
        /* Child process closes up input side of pipe */
        close(fd[0]);

        /* Send "string" through the output side of pipe */
        fpinp = fopen("data.txt", "rb");
        if (fpinp == NULL) {
            perror("child/fopen");
            exit(7);
        }

        fpout = fdopen(fd[1],"wb");
        if (fpout == NULL) {
            perror("child/fdopen");
            exit(8);
        }

        while (1) {
            rlen = fread(buffer,1,sizeof(buffer),fpinp);
            dbgprt("child: LOOP rlen=%zd\n",rlen);

            if (rlen < 0) {
                perror("child/fread");
                exit(9);
            }

            if (rlen <= 0)
                break;

            wlen = fwrite(buffer,1,rlen,fpout);
            dbgprt("child: LOOP wlen=%zd\n",wlen);

            if (wlen < 0) {
                perror("child/fwrite");
                exit(9);
            }
        }

        fclose(fpinp);
        fclose(fpout);

        exit(0);
    }
    else {
        /* Parent process closes up output side of pipe */
        close(fd[1]);

        /* Read in a string from the pipe */
        char *new_data = "new_data.txt";
        fpout = fopen(new_data, "wb");
        if (fpout == NULL) {
            perror("parent/fopen");
            exit(3);
        }

        fpinp = fdopen(fd[0],"rb");
        if (fpinp == NULL) {
            perror("parent/fdopen");
            exit(4);
        }

        while (1) {
            rlen = fread(buffer, 1, sizeof(buffer), fpinp);
            dbgprt("parent: LOOP rlen=%zd\n",rlen);
            if (rlen < 0) {
                perror("parent/fread");
                exit(5);
            }
            if (rlen <= 0)
                break;

            wlen = fwrite(buffer, 1, rlen, fpout);
            dbgprt("parent: LOOP wlen=%zd\n",wlen);
            if (wlen < 0) {
                perror("parent/fwrite");
                exit(6);
            }
        }

        fclose(fpinp);
        fclose(fpout);

        waitpid(childpid,&status,0);
        dbgprt("status=%8.8X\n",status);
    }

    return 0;
}

相关问题