多进程和mmap 实现copy的demo

该博客介绍了一种使用多进程和内存映射(mmap)来复制文件的方法。通过创建多个进程,每个进程负责复制文件的一部分,或者利用mmap直接映射文件到内存进行复制。代码示例展示了如何根据文件大小选择合适的复制策略。
摘要由CSDN通过智能技术生成
#include<sys/mman.h>
#include<fcntl.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<string.h>

#define MAX_LEN 10485760  //10M 大于10M默认每个进程映射10M 修改应为4096的倍数
#define N 10  //进程拷贝  低于10M,选择此方式,默认开十个进程,可修改

int plen,pnum; 
void sys_err(char *str)
{
    perror(str);
    exit(1);
}

int comFile(char *Fname)
{
    int fd;
    if(access(Fname, F_OK))
        fd = open(Fname, O_CREAT|O_WRONLY,0664);
    else
        fd = open(Fname, O_RDONLY);
    return fd;
}

int process_cp(int i, char *sfile, char *dfile)
{
    char buf[1024] = {0};
    int count;
    int sd = open(sfile, O_RDONLY);
    int dd = open(dfile, O_WRONLY);
    if(sd < 0 || dd < 0)
        sys_err("mmap_cp fileOpen");
    lseek(sd, i*plen, SEEK_SET);
    lseek(dd, i*plen, SEEK_SET);

    if(i != N-1 )
    {
        while(plen > 0)
        {
            count = plen > 1024? 1024:plen;
            if(read(sd, buf, count) < 0)
                sys_err("process_read");
            write(dd, buf, count);
            plen -= count;
        }
    }
    else
    {
        while((count = read(sd, buf, 1024)) > 0    )
            write(dd,buf,count);
    }
    return 0;
}


void mmap_cp(int i, char *sfile, char *dfile, int flen)
{
    char *sm, *dm;
    int len;
    int sd = open(sfile, O_RDONLY);
    int dd = open(dfile, O_RDWR);
    if(sd < 0 || dd < 0)
        sys_err("mmap_cp fileOpen");
    len = (i == pnum-1 ? flen -i*plen:plen);  //若为最后一个进程,拷贝长度为剩下所有
    sm = mmap(NULL,len, PROT_READ, MAP_SHARED, sd, i*plen);
    dm = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, dd, i*plen);
    if(sm == MAP_FAILED || dm == MAP_FAILED)
        sys_err("mmap");
    
    memcpy(dm, sm, len);
    munmap(sm, len);
    munmap(dm, len);

}

int main(int argc, char *argv[])
{
    int flen, flag, i = 0, sd, dd;
    pid_t pid;
    if(argc != 3)
        sys_err("./ccp sourceFile DestFile..");

    /**文件初步处理***/
    sd = comFile(argv[1]);
    dd = comFile(argv[2]);
    if(sd < 0 || dd < 0)
        sys_err("open source/dest");
    if((flen =lseek(sd, 0, SEEK_END)) < 0)
        sys_err("get seek ");

    ftruncate(dd, flen); 

    pnum = ((flag = (flen > MAX_LEN ? 1:0)) > 0 ? flen/MAX_LEN+1 : N);  
    //根据文件大小选择何种cp方式
    plen = (flag == 0 ? flen/(pnum-1):MAX_LEN);
    //确定每个进程拷贝的长度
    
    while(i < pnum)
    {
        pid = fork();
        if(pid == 0)
            break;
        i++;
    }
    if(pid == 0) //子进程拷贝
    {
        close(sd);
        close(dd);
        if(flag)
            mmap_cp(i,argv[1],argv[2],flen);    
        else
            process_cp(i,argv[1],argv[2]);
    }
    else if(pid > 0)
        wait(NULL);
    else
        sys_err("fork");

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值