文件的多进程拷贝

假设有一个超大文件,需对其完成拷贝工作。为提高效率,可采用多进程并行拷贝的方法来实现。假设文件
大小为 len,共有 n 个进程对该文件进行拷贝。那每个进程拷贝的字节数应为 len/n。 但未必一定能整除, 我们可
以选择让最后一个进程负责剩余部分拷贝工作。 可使用 len % (len/n)将剩余部分大小求出。
为降低实现复杂度, 可选用 mmap 来实现源、 目标文件的映射,通过指针操作内存地址,设置每个进程拷贝
的起始、结束位置。借助 MAP_SHARED 选项将内存中所做的修改反映到物理磁盘上。
在这里插入图片描述


#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>

#define N 5//进程数量
int main(int argc, char *argv[])
{   
	if (argc!=3)
	{
		printf("Enter like this : ./a.out src_file dst_file");
		exit(1);
	}
	
	int n;
	int fd1, fd2;
    //1. 指定创建子进程的个数

    //2. 打开源文件
	fd1 = open(argv[1], O_RDONLY);
	if (fd1<0)
	{
		perror("open src_file error");
		exit(2);
	}

    //3. 打开目的文件, 不存在则创建
	fd2 = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0664);
	if (fd2 < 0)
	{
		perror("open dst_file error");
		exit(3);
	}
    
    //4. 获取文件大小
	struct stat s_buf;
	int ret = fstat(fd1,&s_buf)
	if (ret<0)
	{
		perror("fstat error");
		exit(4);
	}
	int size = s_buf.st_size;
	
	if (size< N)
    {
		size = N;
    }
    
    //5. 根据文件大小拓展目标文件
	ret = ftruncate(fd2, size);
	if (ret < 0)
	{
		perror("ftruncate error");
		exit(5);
	}

    //6. 为源文件创建映射
	char *mp_src = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd1, 0);
	if (mp_src == MAP_FAILED)
	{
		perror("mmap mp_src error");
		exit(6);
	}
	close(fd1);
    //7. 为目标文件创建映射
	char *mp_des = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0);
	if (mp_des == MAP_FAILED)
	{
		perror("mmap mp_des error");
		exit(7);
	}
	close(fd2);
    //8. 求出每个子进程该拷贝的字节数
	int bs = flen / n;
	int mod = flen % bs;  //求出均分后余下的字节数,让最后一个子进程处理。

	char *temp_src = mp_src;//替身
	char *temp_dst = mp_dst;
    //9. 创建N个子进程
    //10. 子进程完成分块拷贝(注意最后一个子进程拷贝起始位置)
	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, size);
	munmap(mp_dst, size);
    return 0;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值