linux多進程---使用mmap映射實現文件拷貝

1、mmap共享映射區編程

一、建立映射區函數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
 
二、釋放映射區munmap
int munmap(void *addr,size_t lenth); 
addr  傳mmap的返回值
length 傳出映射區長度
 
2、使用mmap映射---多進程拷貝代碼
#include<stdio.h>
#include<sys/mman.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<string.h>
#include <sys/wait.h>

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

    //二、使用fstat獲取文件src的大小,truncate拓展文件dest的大小
    struct stat buf;
    fstat(fd_src,&buf);
    int src_size=buf.st_size;
    truncate(argv[2],src_size);
    //三、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;
    }
    close(fd_src);
    close(fd_dest);
    //四、對文件src的大小分段,fork建立子進程,編寫自定義拷貝函數
    int n=5;//進程數,開闢n個進程
    int paragraph_size=src_size/(n-1);
    int rear_paragraph_size=src_size%(n-1);

    int i;
    for(i=1;i<n;++i){
        pid_t pid=fork();
        if(pid==0){
            break;
        }
    }
    void mmap_copy(char* src,char* dest,int par_sleek,int size);
    //五、父進程中拷貝最後一段,子進程中拷貝其餘段,在父進程中關閉子進程,關閉mmap映射
    if(i<n){//子進程
        int paragraph_sleek=(i-1)*paragraph_size;//計算偏移量
        mmap_copy(mmap_src,mmap_dest,paragraph_sleek,paragraph_size);
    }
    if(i==n){//父進程
        int paragraph_sleek=(i-1)*paragraph_size;//計算偏移量
        mmap_copy(mmap_src,mmap_dest,paragraph_sleek,rear_paragraph_size);
        while(1)//回收子進程
        {
            pid_t wpid=waitpid(-1,NULL,WNOHANG);
            if(wpid==-1){
                break;
            }else if(wpid>0){
                printf("waitpid wpid=%d\n",wpid);
            }
        }
        munmap(mmap_src,src_size);
        munmap(mmap_dest,src_size);
    }
    return 0;
}
void mmap_copy(char* src,char* dest,int par_sleek,int size)
{
    memcpy(dest+par_sleek,src+par_sleek,size);
}

 

3、運行案例截圖函數

一、代碼運行環境spa

Ubuntu-16.04.3-desktop-amd643d

二、運行截圖code

 

 

 

一入編程深似海,多學多查多動手blog

相關文章
相關標籤/搜索