linux多线程---使用mmap映射实现文件拷贝

一、代码实现思路

1、示意图

linux多线程---使用mmap映射实现文件拷贝

 

 

 2、示意图注解

循环创建i个线程,将src文件分为i段拷贝到dest文件中

(1)src文件的大小为src_size,前i-1个线程拷贝的文件大小为src_size/(i-1),第i个线程拷贝的文件大小为src_size%(i-1)

(2)线程i的文件偏移量=i*(src_size(i-1)),线程i的文件拷贝位置=起始位置+线程i的文件偏移量

 

二、使用mmap映射---多线程拷贝代码

 

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

#define PTHREAD_NUM 5  //线程数

struct CopyInfo{
	char* src;
	char* dest;
	int num;
	int src_size;
};

int main(int argc,char *argv[])
{
	if(argc!=3){
		printf("please input correct parameters\n");
		return -1; 
	}   
	//1、打开文件src,dest
	int fd_src=open(argv[1],O_RDONLY);
	int fd_dest=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0664);

	//2、使用fstat获取文件src的大小,truncate拓展文件dest的大小
	struct stat buf;
	fstat(fd_src,&buf);
	int src_size=buf.st_size;
	truncate(argv[2],src_size);
	//3、mmap创建文件src,dest的映射,判断映射返回值,关闭文件描述符
	char* mmap_src=mmap(NULL,src_size,PROT_READ,MAP_PRIVATE,fd_src,0);
	char* mmap_dest=mmap(NULL,src_size,PROT_WRITE,MAP_SHARED,fd_dest,0);
	if(mmap_src==MAP_FAILED||mmap_dest==MAP_FAILED){
		perror("mmap err");
		return -1;
	}
	printf("src_size=%d\n",src_size);
	close(fd_src);
	close(fd_dest);
	//4、对文件src的大小分段,循环创建线程,编写线程函数

	pthread_t tid[PTHREAD_NUM];
	struct CopyInfo copyInfos[PTHREAD_NUM];//创建PTHREAD_NUM个结构体
	void* pthread_copy(void *CoIn);
	for(int i=0;i<PTHREAD_NUM;++i)//每个线程使用一个结构体
	{
		copyInfos[i].src=mmap_src;//可以改进的地方
		copyInfos[i].dest=mmap_dest;//每个结构体的src、dest、src_size大小一样,可以写在一个结构体中
		copyInfos[i].num=i; //可以将num单独写在一个结构体中,然后创建结构体数组
		copyInfos[i].src_size=src_size;
		pthread_create(&tid[i],NULL,pthread_copy,(void*)&copyInfos[i]);
	}
	//5、循环销毁线程,关闭mmap映射
	for(int i=0;i<PTHREAD_NUM;++i)
	{
		pthread_join(tid[i],NULL);
	}

	munmap(mmap_src,src_size);
	munmap(mmap_dest,src_size);

	return 0;
}

void* pthread_copy(void *CopyInfo)
{
	struct CopyInfo* CoIn=(struct CopyInfo*)CopyInfo;
	int par_lseek=CoIn->num*(CoIn->src_size/(PTHREAD_NUM-1));//par_lseek分段偏移量,计算出每段拷贝线程的距离文件起始位置的偏移量
	printf("i=%d  lseek=%d\n",CoIn->num,par_lseek);
	if(CoIn->num<(PTHREAD_NUM-1))
	{
		int copy_size=CoIn->src_size/(PTHREAD_NUM-1);
		memcpy(CoIn->dest+par_lseek,CoIn->src+par_lseek,copy_size);//CoIn->dest+par_lseek:dest文件的起始位置+分段偏移量
	}else //copyInfo->num==(PTHREAD_NUM-1)
	{
		int copy_size=CoIn->src_size%(PTHREAD_NUM-1);
		memcpy(CoIn->dest+par_lseek,CoIn->src+par_lseek,copy_size);
	}
	//memcpy(CoIn->dest+par_lseek,CoIn->src+par_lseek,copy_size); //可以在此处内存拷贝
	return NULL;
}

  

三、运行截图

linux多线程---使用mmap映射实现文件拷贝

 

 

注意事项:

gcc 01_mmap_pthread_copy.c -lpthread    多线程代码编译要加-lpthread,否则会报错

gcc对.c文件直接编译后,会生成a.out的可执行文件

 

 

一入编程深似海,多学多查多动手

 

 

#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<string.h>#include<sys/mman.h>#include<unistd.h>#include<pthread.h>
#define PTHREAD_NUM 5  //线程数
struct CopyInfo{    char* src;    char* dest;    int num;    int src_size;};

 

上一篇:一文读懂区块链稳定币(Stable Coin)


下一篇:dp:322. Coin Change 自下而上的dp