一、代码实现思路
1、示意图
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*)©Infos[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; }
三、运行截图
注意事项:
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;};