Linux 下使用 mmap 和 多个子进程的方式完成 大文件的拷贝。

最近学习了 mmap 函数来完成进程之间的通信, 故有此案例:

文件大小为:  351486000 byte

时间对比: 

1. 单进程拷贝: 0.915s

2. 多进程拷贝: 0.001ms

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

// 检查错误
void check(int ret, const char *msg)
{
    if(-1 == ret)
    {
        perror(msg);
        exit(1);
    }
}

// 将内存buffer开始得size字节数据拷贝到文件fd当中, 从off的指定偏移位置开始拷贝
void copy(char *buffer, int size, int fd, off_t off)
{
    //1. 将文件读写指针移动到指定位置上去.
    lseek(fd, off, SEEK_SET);

    //2. 开始向里面写入内容
    write(fd, buffer, size);
}

int main()
{
    int ret = 0;
    // 1.打开文件 dat
    int fd = open("./dat", O_RDONLY);
    check(fd, "打开./dat失败\n");

    // 2.获取文件的大小
    struct stat s;
    ret = stat("./dat", &s);
    check(ret, "stat('./dat')失败\n");
    off_t size = s.st_size;
    
    // 3.判断目标文件是否存在, 存在退出, 不存在则创建目标文件, 并将目标文件进行拓展
    int fd1 = open("./dest", O_RDWR | O_CREAT | O_EXCL, 0777);
    if(fd1 == -1 && errno & EEXIST)
    {
        perror("file exists!");
        exit(1);
    }
    ret = ftruncate(fd1, size);
    check(ret, "truncate error");
    ret = close(fd1);
    check(ret, "close fd1 failure!\n");
    
    // 4.为此文件创建内存的映射区
    char * ptr = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
    if(ptr ==  MAP_FAILED)
    {
        printf("mmap error!\n");
        exit(1);
    }

    // 创建5个进程
    int each = size / 5, i;
    for(i = 0; i != 5; ++i)
    {
        pid_t id = fork();
        if(id == 0)
        {
            int fd1 = open("./dest", O_RDWR);
            int rest = 0;
            if(i == 4) rest = size % 5;
            copy(ptr + i * each, each + rest, fd1, i * each);
            close(fd1);
            break;
        }
    }
    
    if(i == 5)
    {
        close(fd);
        munmap(ptr, size);
    }
    return 0;
}
发布了17 篇原创文章 · 获赞 23 · 访问量 3413

猜你喜欢

转载自blog.csdn.net/DO_HACKER/article/details/100594062