使用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++中事件机制的简洁实现及需要放弃的特性

    C++中事件机制的简洁实现及需要放弃的特性

    事件模型是被广泛使用的好东西,但是C++标准库里没有现成的,现在VC11可以用在XP下了,那么就痛快的拿起C++11提供的先进设施组合出一个轻便的实现吧感兴趣的朋友可以了解下,或许对你有所帮助
    2013-02-02
  • 基于C++实现掷双骰游戏的示例代码

    基于C++实现掷双骰游戏的示例代码

    在最流行的博彩游戏中有一种名为“掷双骰”(craps)的骰子游戏,这种游戏在世界各地的娱乐场所和大街小巷非常受欢迎。本文将用C++语言实现这一游戏,需要的可以参考一下
    2022-03-03
  • C++实现CreatThread函数主线程与工作线程交互的方法

    C++实现CreatThread函数主线程与工作线程交互的方法

    这篇文章主要介绍了C++实现CreatThread函数主线程与工作线程交互的方法,是Windows应用程序设计中非常实用的方法,需要的朋友可以参考下
    2014-10-10
  • 一文详解如何在VS Code上搭建C/C++开发环境

    一文详解如何在VS Code上搭建C/C++开发环境

    VSCode是由微软开发的一款免费、开源、跨平台的文本编辑器,它具有许多强大的功能,这篇文章主要给大家介绍了关于如何在VS Code上搭建C/C++开发环境的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • C语言多文件编程问题解析

    C语言多文件编程问题解析

    在某些场景中,考虑到编译效率和可移植性,#pragma once 和 #ifndef 经常被结合使用来避免头文件被 重复引入,这里介绍用 _Pragma 操作符避免头文件重复引入的问题,感兴趣的朋友跟随小编一起看看吧
    2022-12-12
  • 用c语言实现《狼人杀》游戏发牌系统

    用c语言实现《狼人杀》游戏发牌系统

    大家好,本篇文章主要讲的是用c语言实现《狼人杀》游戏发牌系统,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • sublime text3搭建配置c语言编译环境的详细图解教程(小白级)

    sublime text3搭建配置c语言编译环境的详细图解教程(小白级)

    这篇文章主要介绍了sublime text3搭建配置c语言编译环境,详细图解,小白教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • C语言回调函数的简单运用

    C语言回调函数的简单运用

    回调函数就是函数指针变量作为另外一个函数的参数而使用的一种应用情形。本文就详细的介绍一下C语言回调函数的简单运用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • C/C++静态类和this指针详解及实例代码

    C/C++静态类和this指针详解及实例代码

    这篇文章主要介绍了 C/C++静态类和this指针详解及实例代码的相关资料,需要的朋友可以参考下
    2017-02-02
  • C语言深入浅出解析二叉树

    C语言深入浅出解析二叉树

    二叉树可以简单理解为对于一个节点来说,最多拥有一个上级节点,同时最多具备左右两个下级节点的数据结构。本文将详细介绍一下C++中二叉树的实现和遍历,需要的可以参考一下
    2022-03-03

最新评论