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

一、mmap共享映射区

1、创建映射区函数mmap
void *mmap(void *addr,size_t length,int prot,int flags,int fd,off_t offset);
addr  传NULL
length  传映射区长度
prot 
PROT_READ 可读
PROT_WRITE  可写
flags
MAP_SHARED 共享的;对内存的修改会影响到源文件(源文件即fd对应的文件)
MAP_PRIVATE 私有的;对内存的修改不会影响源文件
fd 文件描述符,open打开一个文件
offset  偏移量
返回值:
成功返回 可用的内存首地址  
失败返回 MAP_FAILED
 
2、释放映射区munmap
int munmap(void *addr,size_t lenth); 
addr  传mmap的返回值
length 传出映射区长度
 
二、使用mmap映射---多进程拷贝代码

 

 1 #include<stdio.h>
 2 #include<sys/mman.h>
 3 #include<unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <fcntl.h>
 7 #include<string.h>
 8 #include <sys/wait.h>
 9 
10 int main(int argc,char* argv[])
11 {
12     if(argc!=3){
13         printf("please input correct parameters\n");
14         return -1;
15     }
16     //1、打开文件src,dest
17     int fd_src=open(argv[1],O_RDONLY);
18     int fd_dest=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0664);
19 
20     //2、使用fstat获取文件src的大小,truncate拓展文件dest的大小
21     struct stat buf;
22     fstat(fd_src,&buf);
23     int src_size=buf.st_size;
24     truncate(argv[2],src_size);
25     //3、mmap创建文件src,dest的映射,判断映射返回值,关闭文件描述符
26     char* mmap_src=mmap(NULL,src_size,PROT_READ,MAP_PRIVATE,fd_src,0);
27     char* mmap_dest=mmap(NULL,src_size,PROT_WRITE,MAP_SHARED,fd_dest,0);
28     if(mmap_src==MAP_FAILED||mmap_dest==MAP_FAILED){
29         perror("mmap err");
30         return -1;
31     }
32     close(fd_src);
33     close(fd_dest);
34     //4、对文件src的大小分段,fork创建子进程,编写自定义拷贝函数
35     int n=5;//进程数,开辟n个进程
36     int paragraph_size=src_size/(n-1);
37     int rear_paragraph_size=src_size%(n-1);
38 
39     int i;
40     for(i=1;i<n;++i){
41         pid_t pid=fork();
42         if(pid==0){
43             break;
44         }
45     }
46     void mmap_copy(char* src,char* dest,int par_lseek,int size);
47     //5、父进程中拷贝最后一段,子进程中拷贝其他段,在父进程中关闭子进程,关闭mmap映射
48     if(i<n){//子进程
49         int paragraph_lseek=(i-1)*paragraph_size;//计算偏移量
50         mmap_copy(mmap_src,mmap_dest,paragraph_lseek,paragraph_size);
51     }
52     if(i==n){//父进程
53         int paragraph_lseek=(i-1)*paragraph_size;//计算偏移量
54         mmap_copy(mmap_src,mmap_dest,paragraph_lseek,rear_paragraph_size);
55         while(1)//回收子进程,也可以用信号回收
56         {
57             pid_t wpid=waitpid(-1,NULL,WNOHANG);
58             if(wpid==-1){
59                 break;
60             }else if(wpid>0){
61                 printf("waitpid wpid=%d\n",wpid);
62             }
63         }
64         munmap(mmap_src,src_size);
65         munmap(mmap_dest,src_size);
66     }
67     return 0;
68 }
69 void mmap_copy(char* src,char* dest,int par_lseek,int size)
70 {
71     memcpy(dest+par_lseek,src+par_lseek,size);
72 }

 

  

  

三、运行案例截图

1、代码运行环境

Ubuntu-16.04.3-desktop-amd64

2、运行截图

 

 

 

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

 

 

posted @ 2021-01-16 00:26  阿斯顿之意  阅读(545)  评论(0)    收藏  举报