使用mmap实现多进程对大文件拷贝

本文实例为大家分享了mmap实现文件多进程拷贝,供大家参考,具体内容如下

假设有一个超大文件,需对其完成拷贝工作。为提高效率,可采用多进程并行拷贝的方法来实现。假设文件大小为len,共有n个进程对该文件进行拷贝。那每个进程拷贝的字节数应为len/n。但未必一定能整除,我们可以选择让最后一个进程负责剩余部分拷贝工作。可使用len % (len/n)将剩余部分大小求出。

为降低实现复杂度,可选用mmap来实现源、目标文件的映射,通过指针操作内存地址,设置每个进程拷贝的起始、结束位置。借助MAP_SHARED选项将内存中所做的修改反映到物理磁盘上。

思路:

//1. 指定创建子进程的个数
//2. 打开源文件
//3. 打开目的文件, 不存在则创建
//4. 获取文件大小
//5. 根据文件大小拓展目标文件
//6. 为源文件创建映射
//7. 为目标文件创建映射
//8. 求出每个子进程该拷贝的字节数
//9. 创建N个子进程
//10. 子进程完成分块拷贝(注意最后一个子进程拷贝起始位置)
//11. 释放映射区

代码如下:

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

int main(int argc,char*argv[])
{
 int n;
 if(argc < 3 || argc > 4)
 {
 printf("Enter like this : ./a.out file_src file_dst [proc_number]\n");
 exit(1);
 }
 else if(argc == 3) //用户未指定,默认创建5个进程。
 n = 5;
 else
 n = atoi(argv[3]);

 //2.打开源文件
 int fd_src = open(argv[1],O_RDONLY);
 if(fd_src < 0)
 {
 perror("open");
 exit(2);
 }
 //3.打开目标文件,不存在就创建,存在则截断为0的大小。
 int fd_dst = open(argv[2],O_RDWR |O_CREAT |O_TRUNC,0664);
 if(fd_dst < 0)
 {
 perror("open");
 exit(3);
 }
 //4.获取源文件大小。
 struct stat sbuf;
 int ret = fstat(fd_src,&sbuf); //fd_src所指向的文件信息保存到结构体sbuf中。
 if(ret < 0)
 {
 perror("fstat");
 exit(4);
 }
 int flen = sbuf.st_size; //源文件大小。
 if(flen < n) //文件长度小于进程个数。
 {
 n = flen;
 }
 //5.根据文件大小拓展目标文件。
 ret = ftruncate(fd_dst,flen);//将参数fd指定的文件大小改为参数length指定的大小
 if(ret < 0)
 {
 perror("ftruncate");
 exit(5);
 }
 //6.为源文件创建映射。
// void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
//addr == NULL,表示内核选择一个合适的地址创建一个length大小的共享内存,
 char *mp_src = (char*)mmap(NULL,flen,PROT_READ,MAP_SHARED,fd_src,0); //0,表示将fd_src所指向的文件从起始映射到共享内存中,共享内存的权限为只读,进程间共享。
 if(mp_src == MAP_FAILED) //mmap一定要检查返回值。
 {
 perror("mmap");
 exit(6);
 }
 close(fd_src);

 //7.为目标文件创建映射。
 char *mp_dst = (char*)mmap(NULL,flen,PROT_READ|PROT_WRITE,MAP_SHARED,fd_dst,0);
 if(mp_dst == MAP_FAILED) //mmap一定要检查返回值。
 {
 perror("mmap");
 exit(7);
 }
 close(fd_dst);

 //8.求出每个进程拷贝的字节数。
 int bs = flen / n;
 int mod = flen % bs; //求出均分后余下的字节数,让最后一个子进程处理。

 char *temp_src = mp_src;
 char *temp_dst = mp_dst;

 //9.创建n个子进程。
 int i ;
 pid_t pid;
 for(i = 0; i < n; ++i)
 {
 printf("create %dth proc\n",i);
 if( (pid =fork()) == 0 )
  break;
 }
 if(n == i) //父进程。
 {
 int j = 0;
 for(j = 0; j < n; ++j)
  wait(NULL);
 }
 else if(i == (n-1)) //10.子进程拷贝,最后一个子进程,它多处理均分后剩下的字节数。
 {
 printf("i = %d\n",i);
 memcpy(temp_dst+i*bs,temp_src+i*bs,bs+mod);
 }
 else if(i == 0)
 {
 printf("i = %d\n",i);
 memcpy(temp_dst,temp_src,bs);
 }
 else
 {
 printf("i = %d\n",i);
 memcpy(temp_dst+i*bs,temp_src+i*bs,bs);
 }

 //11.释放映射区。

 munmap(mp_src,flen);
 munmap(mp_dst,flen);

 return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 利用mmap实现文件拷贝功能

    利用mmap实现的一个文件拷贝例子,供大家参考,具体内容如下 /* * gcc -Wall -O3 -o copy_mmap copy_mmap.c */ #include < stdio.h > #include < stdlib.h > #include < string .h > /* for memcpy */ #include < strings.h > #include < sys / mman.h > #include < s

  • 使用mmap实现大文件的复制(单进程和多进程)

    使用mmap实现大文件的复制,供大家参考,具体内容如下 典型的文件复制的流程是: 1.读取(fread)被复制的文件的内容. 2.写入(fwrite)到新的文件中去. 使用mmap进行文件复制的流程则是: 1.为被复制的文件已经新文件分别进行mmap映射. 2.将被复制的文件映射的内存的内容复制到新文件映射的内存. 在知道了基本原理之后,让我们看看具体的做法,本文只分析使用mmap进行大文件复制的方法 具体的做法 先了解一些使用mmap时,应当注意的细节: 文件的大小必须要大于等于内存映射区的大

  • 使用mmap实现多进程对大文件拷贝

    本文实例为大家分享了mmap实现文件多进程拷贝,供大家参考,具体内容如下 假设有一个超大文件,需对其完成拷贝工作.为提高效率,可采用多进程并行拷贝的方法来实现.假设文件大小为len,共有n个进程对该文件进行拷贝.那每个进程拷贝的字节数应为len/n.但未必一定能整除,我们可以选择让最后一个进程负责剩余部分拷贝工作.可使用len % (len/n)将剩余部分大小求出. 为降低实现复杂度,可选用mmap来实现源.目标文件的映射,通过指针操作内存地址,设置每个进程拷贝的起始.结束位置.借助MAP_SH

  • java高效实现大文件拷贝功能

    在java中,FileChannel类中有一些优化方法可以提高传输的效率,其中transferTo( )和 transferFrom( )方法允许将一个通道交叉连接到另一个通道,而不需要通过一个缓冲区来传递数据.只有FileChannel类有这两个方法,因此 channel-to-channel 传输中通道之一必须是 FileChannel.不能在sock通道之间传输数据,不过socket 通道实现WritableByteChannel 和 ReadableByteChannel 接口,因此文件

  • Node.js本地文件操作之文件拷贝与目录遍历的方法

    文件拷贝 NodeJS 提供了基本的文件操作 API,但是像文件拷贝这种高级功能就没有提供,因此我们先拿文件拷贝程序练手.与 copy 命令类似,我们的程序需要能接受源文件路径与目标文件路径两个参数. 小文件拷贝 我们使用 NodeJS 内置的 fs 模块简单实现这个程序如下. var fs = require('fs'); function copy(src, dst) { fs.writeFileSync(dst, fs.readFileSync(src)); } function main

  • linux下如何实现快速拷贝大文件

    拷贝数据 远程拷贝数据的时候,我们一般使用rsync命令,但是如果拷贝大量的小文件,会导致rsync的传输速度慢.使用tar pv lz4打包压缩传输,可以解决这问题,使用这个方法,等同于使用scp.rsync传输大文件. 实测,使用rsync传输1200G,单个文件大小为几十KB~2GB,千兆网卡,需要同时跑6个rsync才能把带宽跑满,每个速度20MB左右,速度波动大.每分钟可以拷贝4.5GB左右. 但是,使用tar pv lz4,跑一个就可以了,而且速度波动小.每分钟可以拷贝6.8GB左右

  • SSM框架+Plupload实现分块上传大文件示例

    关于Plupload的介绍,相信它的官网http://www.plupload.com/已经给得很详细了.Plupload的上传原理简单点说,就是将用户选中的文件(可多个)分隔成一个个小块,依次向服务器上传,这是它能驾驭上传大文件的原因之一,而且在这个过程可以暂停上传,暂停后再继续上传(异于断点续传).最重要的是,从头到尾没有一点点UI阻塞,保证了用户体验.下面会开始讲Plupload的实现流程,分析原理,并在最后给出效果图. 在此之前先说说我的项目,做的j2ee项目运用到spring+Spri

  • c#通过DES加密算法加密大文件的方法

    本文实例讲述了c#通过DES加密算法加密大文件的方法.分享给大家供大家参考.具体实现方法如下: using System.Collections; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using Syst

  • iOS大文件的分片上传和断点上传的实现代码

    今天小编抽空给大家分享一些大文件的上传的问题!断点续传和分片上传.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件切片(分块),但这不是我们现在说的重点,我们要做的事是保证在网络中断后1G的文件已上传的那部分在下次网络连接时不必再重传.所以我们本地在上传的时候,要将大文件进行分片,比如分成1024*1024B,即将大文件分成1M的片进行上传,服务器在接收后,再将这些片合并成原始文件,这

  • 使用Python读取大文件的方法

    背景 最近处理文本文档时(文件约2GB大小),出现memoryError错误和文件读取太慢的问题,后来找到了两种比较快Large File Reading 的方法,本文将介绍这两种读取方法. 准备工作 我们谈到"文本处理"时,我们通常是指处理的内容.Python 将文本文件的内容读入可以操作的字符串变量非常容易.文件对象提供了三个"读"方法: .read()..readline() 和 .readlines().每种方法可以接受一个变量以限制每次读取的数据量,但它们

随机推荐