多线程

来源:互联网 发布:ubuntu 16.04输入法 编辑:程序博客网 时间:2024/06/05 08:47

多线程拷贝命令的实现,如:./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