多线程

3 篇文章 0 订阅

多线程拷贝命令的实现,如:./my_cp src_file dest_file N(拷贝线程个数)
思路:先把src_file用mmap映射到内存里面,私人模式,然后创建dest_file,文件大小于src一样,也映射到内存空间去,然后把根据线程个数,把文件分割.
定义一个结构体,元素有每个线程要拷贝的起始指针位置,块大小,以及这是第几个线程.
定义一个全局整形数组指针,指向一个动态数组空间,数组的大小和线程的个数一致,用于进度条.
代码的实现:

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

int *array;

void sys_err(const char *str)
{
    perror(str);
    exit(0);
}

struct cp {
    char *srcm_add;
    char *destm_add;
    int thread_num;
    int block_size;
};

void *thread_cpy(void *arg)
{
    struct cp *im = (struct cp *)arg;

    int block = im->block_size;
    char *srcm_add = im->srcm_add;
    char *destm_add = im->destm_add;

    while(block--) { //One byte of a byte copy
        *destm_add++ = *srcm_add++;
        array[im->thread_num]++;
        usleep(1000);
        }

    free(im);
}

int main(int argc, char *argv[])
{
    int fdsrc, fddest;
    int src_size = 0;
    char *srcm_add, *destm_add;
    int block_size;
    int thread_num;
    pthread_t tid;
    struct cp *im;
    int i;
    int err;
    int sum = 0;
    pthread_attr_t attr;
    struct stat st;

    if (argc < 3) {
        printf("./a.out srcfile destfile\n");
        exit(1);
    }

    /* open fdsrc ,get fdsrc size*/
    if((fdsrc = open(argv[1], O_RDONLY)) < 0)
        sys_err("open src");
    if((src_size = lseek(fdsrc, 0, SEEK_END)) < 0)
        sys_err("lseek fdsrc");
    if(stat(argv[1], &st))
        sys_err("stat");

    st.st_mode &= 0777;

    /* create fddest, mode and size*/
    if((fddest = open(argv[2], O_CREAT|O_RDWR, st.st_mode)) < 0)
        sys_err("open dest");
    if(lseek(fddest, src_size-1, SEEK_SET) < 0)
        sys_err("lseek dest");
    if(write(fddest, "\0", 1) < 0)
        sys_err("write creat dest");

    /* block number*/
    if(argc == 3)
        thread_num = 5;
    else
        thread_num = atoi(argv[3]);

    /* chick num */
    array = calloc(sizeof(int), thread_num);

    /* copy file to mmap */
    srcm_add = mmap(NULL, src_size, PROT_READ, MAP_PRIVATE, fdsrc, 0);
    destm_add = mmap(NULL,src_size, PROT_WRITE, MAP_SHARED, fddest, 0);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    /* create thread */
    for (i=0; i<thread_num; i++) {
        if(i == (thread_num-1))
            block_size = src_size/thread_num + src_size%thread_num;
        else
            block_size = src_size/thread_num;

        im = calloc(sizeof(struct cp), 1);
        im->srcm_add = srcm_add + i * (src_size/thread_num);
        im->destm_add = destm_add + i * (src_size/thread_num);
        im->block_size = block_size;

        im->thread_num = i;

        err = pthread_create(&tid, &attr, thread_cpy, (void *)im);
        if(err != 0)
            fprintf(stderr, "%s\n", strerror(err));
    }

    int j, k = 1;

    j = src_size/20;

    do {
        sum = 0;
        for (i=0; i<thread_num; i++)
            sum += array[i];

        if(sum > j*k) {
            k++;
            write(STDOUT_FILENO, "==", 2);
        }
        usleep(10000);
    } while(sum < src_size);
    printf("\n");

    free(array);

    munmap(srcm_add, src_size);
    munmap(destm_add, src_size);

    return 0;
}

注意:如果要映射的文件过大,不能一下子全部映射内存里面,要一部分一部分的映射到内存里面,然后在一点一点往另一个内存拷贝,但还要注意,mmap的最小偏移量4096。

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

int *array;

void sys_err(const char *str)
{
    perror(str);
    exit(0);
}

struct cp {
    char *srcm_add;
    char *destm_add;
    int thread_num;
    int block_size;
};

void *thread_cpy(void *arg)
{
    struct cp *im = (struct cp *)arg;

    int block = im->block_size;
    char *srcm_add = im->srcm_add;
    char *destm_add = im->destm_add;

    while(block--) { //One byte of a byte copy
        *destm_add++ = *srcm_add++;
        array[im->thread_num]++;
        usleep(100);
    }
    free(im);
}

int main(int argc, char *argv[])
{
    int fdsrc, fddest;
    int src_size = 0;
    char *srcm_add, *destm_add;
    int block_size;
    int thread_num;
    pthread_t tid;
    struct cp *im;
    int i;
    int err;
    int sum = 0;
    pthread_attr_t attr;
    struct stat st;

    int page_size;
    int page_num;
    int page_count = 0;

    if (argc < 3) {
        printf("./a.out srcfile destfile\n");
        exit(1);
    }

    /* open fdsrc ,get fdsrc size*/
    if((fdsrc = open(argv[1], O_RDONLY)) < 0)
        sys_err("open src");
    if((src_size = lseek(fdsrc, 0, SEEK_END)) < 0)
        sys_err("lseek fdsrc");
    if(stat(argv[1], &st))
        sys_err("stat");

    st.st_mode &= 0777;

    /* create fddest, and set size*/
    if((fddest = open(argv[2], O_CREAT|O_RDWR, st.st_mode)) < 0)
        sys_err("open dest");
    if(lseek(fddest, src_size-1, SEEK_SET) < 0)
        sys_err("lseek dest");
    if(write(fddest, "\0", 1) < 0)
        sys_err("write creat dest");

    if(argc == 3)
        thread_num = 5;
    else
        thread_num = atoi(argv[3]);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    if(src_size > 4096) {
        page_num = src_size/4096 + 1;
        for(page_count=0; page_count<page_num; page_count++) {

            array = calloc(sizeof(int), thread_num);

            if(page_count == (page_num-1))
                page_size = src_size%4096;
            else
                page_size = 4096;

            srcm_add = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, fdsrc, 4096*page_count);
            destm_add = mmap(NULL,page_size, PROT_WRITE, MAP_SHARED, fddest, 4096*page_count);

            for (i=0; i<thread_num; i++) {
                if(i == (thread_num-1))
                    block_size = page_size/thread_num + page_size%thread_num;
                else
                    block_size = page_size/thread_num;

                im = calloc(sizeof(struct cp), 1);
                im->srcm_add = srcm_add + i * (page_size/thread_num);
                im->destm_add = destm_add + i * (page_size/thread_num);
                im->block_size = block_size;

                im->thread_num = i;

                err = pthread_create(&tid, &attr, thread_cpy, (void *)im);
                if(err != 0)
                    fprintf(stderr, "%s\n", strerror(err));
            }

            int j, k = 1;

            j = page_size/20;

            do {
                sum = 0;
                for (i=0; i<thread_num; i++)
                    sum += array[i];
                if(sum > j*k) {
                    k++;
                    write(STDOUT_FILENO, "==", 2);
                }
                usleep(10000);
            } while(sum < page_size);
             printf("\n");

            free(array);

            munmap(srcm_add, page_size);
            munmap(destm_add, page_size);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值