簡體   English   中英

pipe 使用文件 fread 和 fwrite 將文件從一個進程發送到另一個進程

[英]pipe with file fread & fwrite send file from one process to another

我實現了一個 pipe,它從一個 100MB 的進程數據文件大小“傳輸”到另一個進程。

從一個過程到另一個過程的整個發送效果很好,但它需要很長時間......大約 2.5 分鍾以上。

我想將我的函數更改為 fread&fwrite 以使 function 更快,而不是每次讀取一個字符我如何使用 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;
}

幾個問題...

在您的原始代碼中,主要問題 [速度方面] 是使用長度為 1 的readwrite

此外,盡管 stream 可能會稍微補償fgetc ,但它仍然是一次一個字節。

我想出的解決方案是實施 William Pursell 的建議:使用fdopen將 stdio stream(即FILE * )附加到 pipe。

我們可以為父母和孩子這樣做。

然后,只需在兩個進程中循環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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM