您的位置:首页 > 运维架构 > Linux

多线程

2015-12-01 21:14 429 查看
多线程拷贝命令的实现,如:./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
b97b
*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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息