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

 更新时间:2019年10月16日 15:53:27   作者:hj605635529  
这篇文章主要介绍了使用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;
}

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

相关文章

  • C++ Boost Foreach超详细分析讲解

    C++ Boost Foreach超详细分析讲解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C++ ofstream与ifstream详细用法

    C++ ofstream与ifstream详细用法

    ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间
    2013-07-07
  • c语言左移和右移的示例详解

    c语言左移和右移的示例详解

    这篇文章主要介绍了c语言左移和右移的示例详解,移位操作符的两个操作数必须是整型的。整个移位表达式的值的类型也是整型的,而且,左移位操作符与右移位操作符的运算并不对称。
    2020-07-07
  • C++实现LeetCode(112.二叉树的路径和)

    C++实现LeetCode(112.二叉树的路径和)

    这篇文章主要介绍了C++实现LeetCode(112.二叉树的路径和),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • 正确理解C++的构造函数和析构函数

    正确理解C++的构造函数和析构函数

    在C++的学习中,可以把类当作一个模具,类实例化出来的对象就是根据这个模具所产生的实体,对象看作是自己创建的一个新的数据类型。本文主要介绍了类对象通过拷贝函数进行初始化,分析类对象的内存模型,以及通过this指针实现更复杂的功能。最后介绍了析构函数的基础知识
    2021-06-06
  • 基于C语言实现三子棋小游戏

    基于C语言实现三子棋小游戏

    这篇文章主要为大家详细介绍了基于C语言实现三子棋小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • 一文详解C语言操作符

    一文详解C语言操作符

    这篇文章主要详细介绍了C语言的操作符,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • CMake自动管理C/C++项目的实现

    CMake自动管理C/C++项目的实现

    CMake是一个强大的构建系统,用于跨平台管理C/C++项目的编译过程,本文主要介绍了CMake自动管理C/C++项目的实现,具有一定的参考价值,感兴趣的可以了解一下
    2025-02-02
  • C++提取文件中信息的方法

    C++提取文件中信息的方法

    这篇文章主要为大家详细介绍了C++提取文件中信息的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • C++使用泛型导致的膨胀问题

    C++使用泛型导致的膨胀问题

    这篇文章主要介绍了C++使用泛型导致的膨胀,智能家居主机的嵌入式平台上使用C++进行开发。FLASH存储空间有限,这是必须要考虑的因素,一定要重视,下面我们一起进入文章看看详细内容
    2021-11-11

最新评论