单线程和多进程实现文件的复制(mmap方法)
mmap实现大文件的复制
- 单线程和多进程实现文件的复制(mmap方法)
- 一、单线程实现
- 二、多进程实现
一般文件实现方法:
1.读取(fread)要复制的文件
2.写入(fwrite)目标文件
mmap实现方法:
1.源文件和目标映射到内存空间
2.memcpy进行拷贝
一、单线程实现
#include <cstdio>
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <memory.h>
using namespace std;int file_size(char* filename)
{struct stat statbuf;stat(filename,&statbuf);int size = statbuf.st_size;return size;}int main(int argc,char* argv[])
{//参数一:要拷贝的文件路径名if (argv[1] == ""){printf("参数不能为空");exit(1);}//参数二:目标文件路径名if (argv[2] == ""){printf("参数不能为空");exit(1);}void* s_ptr;void* o_ptr;int s_ret=0,o_ret=0;//打开源文件,只读模式s_ret = open(argv[1],O_RDONLY);if (s_ret == -1){perror("file error:");exit(1);}//目标模式,没有则创建,只写模式o_ret = open(argv[2], O_CREAT|O_RDWR,0644);if (o_ret == -1){perror("file error:");exit(1);}//获取文件大小int size = file_size(argv[1]);//printf("file size: %d \n",size);//扩展目标文件ftruncate(o_ret,size);//内存映射s_ptr=mmap(NULL, size, PROT_READ, MAP_PRIVATE, s_ret, 0);o_ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, o_ret, 0);if (o_ptr == MAP_FAILED){perror("s_ptr mmap error:");exit(1);}//关闭文件描述符close(s_ret);close(o_ret);//实现拷贝memcpy(o_ptr,s_ptr,size);//释放映射空间munmap(s_ptr,size);munmap(o_ptr, size);return 0;
}
二、多进程实现
#include <cstdio>
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <memory.h>
#include <sys/wait.h>
using namespace std;int file_size(char* filename)
{struct stat statbuf;stat(filename,&statbuf);int size = statbuf.st_size;return size;}int main(int argc,char* argv[])
{//参数一:要拷贝的文件路径名if (argv[1] == ""){printf("参数不能为空");exit(1);}//参数二:目标文件路径名if (argv[2] == ""){printf("参数不能为空");exit(1);}char* s_ptr;char* o_ptr;int n = 5;//创建子进程的个数int s_ret=0,o_ret=0;int i=0;//打开源文件,只读模式s_ret = open(argv[1],O_RDONLY);if (s_ret == -1){perror("file error:");exit(1);}//目标模式,没有则创建,只写模式o_ret = open(argv[2], O_CREAT|O_RDWR,0644);if (o_ret == -1){perror("file error:");exit(1);}//获取文件大小int size = file_size(argv[1]);//printf("file size: %d \n",size);//扩展目标文件ftruncate(o_ret,size);//内存映射s_ptr=(char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, s_ret, 0);o_ptr = (char*)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, o_ret, 0);if (o_ptr == MAP_FAILED){perror("s_ptr mmap error:");exit(1);}//关闭文件描述符close(s_ret);close(o_ret);//实现拷贝int each_size = size / n;int last_size = size - (n * each_size);pid_t pid;//循环创建子进程for (i = 0; i < n; i++){pid = fork();if (pid == 0){break;//子进程退出循环}}if (n == i)//主进程{sleep(i);memcpy(o_ptr + i * each_size, s_ptr + i * each_size, last_size);waitpid(-1,NULL, WNOHANG);}else{sleep(i);memcpy(o_ptr + i * each_size, s_ptr+ i * each_size, each_size);}//释放映射空间munmap(s_ptr,size);munmap(o_ptr, size);return 0;
}
不完美的地方
主进程只是采用sleep函数来避免子进程变成僵尸进程,用信号的方式可以改进。