带进度条的多线程拷贝

 

 

---------- SUB_FUN.C
#include "mul_cp.h"
extern char *src_addr, *dest_addr;
static char *sub_bar(int gain, int all, char *buf, int len, int num)
{
    int block = len/num;
    if(len % num != 0)
        block += 1;

    int i;
    for(i = 0; i<block; i++)
        if(i <= block * gain /all)
            buf[i] = '>';
        else
            buf[i] = ' ';
    buf[i] = 0;
    return buf;
}

void disp_bar(cp_task *task, int num)
{
	int i, i_gain;
	int cur = 0, all = 0;
	char bar[60];
    char *sch;

	for(i = 0; i<num; i++)
		all += task[i].off;

	while(cur < all){
		usleep(1000);
		cur = 0;
		for(i = 0; i<num; i++) {
			i_gain = task[i].cur_gain;
			cur += i_gain;
            sch = sub_bar(i_gain, task[0].off, bar, sizeof(bar), num);
			printf("%s", sch);
		}
		printf("]%4.1f%%\r[", cur*100.0/all);
	}
	puts("");
}


int assign_task(int src_filesize, int num, cp_task *task_sch)
{
    int block_size;
	block_size = src_filesize / num;
	if(src_filesize % num != 0) // 如果不能整除,块大小= 总数/份数 + 1
		block_size += 1; 

    int i;
    for(i = 0; i < num; i++){
		task_sch[i].id = i;
        task_sch[i].base = i * block_size; 
        task_sch[i].off = block_size;
    }
	task_sch[num-1].off = src_filesize - block_size * (num - 1);
}

int parse_arg(const int argc, const char **argv, const char **src, const char **dest, int *pthread_num)
{
	if(argc != 4)
	{
		printf("%s %s %s %s\n",argv[0],  "<thread_number>", "<src file>", "<dest file>");
		exit(0);
	}

	*pthread_num = atoi(argv[1]);
    *src = argv[2];
    *dest = argv[3];

    return *pthread_num;
}

int create_map(int src_filesize, const char *src_file, const char *dest_file, char **src_addr, char **dest_addr)
{
    int src_fd, dest_fd;
    if((src_fd = open(src_file, O_RDONLY)) < 0){
        perror("open src_fd");
        exit(1);
    }

    if((dest_fd = open(dest_file, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0){
        perror("open dest_fd");
        exit(2);
    }
	lseek(dest_fd, src_filesize-1, SEEK_SET); // 目标文件大小必须和源文件大小相等方可对等映射
	write(dest_fd, "", 1);

	*src_addr = mmap(NULL, src_filesize, PROT_READ, MAP_SHARED, src_fd, 0);
	if(*src_addr == MAP_FAILED){
		perror("mmap");
		exit(3);
	}

    *dest_addr = mmap(*src_addr + src_filesize, src_filesize, PROT_WRITE, MAP_SHARED, dest_fd, 0);
	if(*dest_addr == MAP_FAILED){
		perror("mmap");
		exit(4);
	}

    close(src_fd);
    close(dest_fd);
}

int get_filesize(const char *name) 
{
	int fd = open(name, O_APPEND);
	if(fd < 0)
	{
		perror("get_filesize-->open:");
		exit(-1);
	}
	off_t off = lseek(fd, 0, SEEK_END);	
	close(fd);
	return off;
}

---------- MUL_CP.H
#ifndef MUL_CP
#define MUL_CP

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

#define gotoxy(line, cols)	fprintf(stderr, "\033[%d;%dH", (line),(cols))
#define my_hide_curse() 	fprintf(stderr, "\033[?25l")
#define my_show_curse() 	fprintf(stderr, "\033[?25h")

typedef struct {
		int id;
        int base;
        int off;
        int cur_gain;
}cp_task;

void disp_bar(cp_task *task, int num);
static char *sub_bar(int gain, int all, char *buf, int len, int num);
int assign_task(int src_filesize, int num, cp_task *task_sch);
int parse_arg(const int argc, const char **argv, const char **src, const char **dest, int *pthread_num);
int create_map(int src_filesize, const char *src_file, const char *dest_file, char **src_addr, char **dest_addr);

#endif

---------- MUL_CP.C
#include "mul_cp.h"

char *src_addr, *dest_addr; // 映射的文件内存地址;

static void copy(char *src_addr, char *dest_addr, cp_task *task)
{
	char *src = src_addr + task->base;
	char *dest = dest_addr + task->base;
	int i;	
	for(i = 0; i < task->off; i++){
		 task->cur_gain = i+1;
		 dest[i] = src[i];
         usleep(100);
	}
}

void *mul_cp(void *arg)
{
	cp_task *p = arg;
	copy(src_addr, dest_addr, p);
}

void show_curse(int arg)
{
    my_show_curse();
    puts("");
    exit(0); // 主线程退出, 如果没有,则其他线程继续运行
}

int main(const int argc, const char *argv[])
{
    // 0. 初始化
    signal(SIGINT, show_curse);
    my_hide_curse();

    // 1. 命令行解析
    const char *src_file;
    const char *dest_file;
    int pthread_num;
	setbuf(stdout, NULL);
    parse_arg(argc, argv, &src_file, &dest_file, &pthread_num);

    // 2. 获取src文件属性,如文件大小
    int src_filesize;
    src_filesize = get_filesize(src_file);
	
	// 3. 创建映射文件
    create_map(src_filesize, src_file, dest_file, &src_addr, &dest_addr);

    // 4. 分派任务
    cp_task task_sch[pthread_num];
    memset(&task_sch, 0, sizeof(task_sch));
	assign_task(src_filesize, pthread_num, task_sch);

    // 5. 创建多线程
	int i;
	pthread_t tid[pthread_num];
    for(i = 0; i<pthread_num; i++)
        pthread_create(tid+i, NULL, mul_cp, task_sch+i);
	
	// 6. 显示下载进度
    disp_bar(task_sch, pthread_num);

	// 7. 线程回收等待
	for(i = 0; i<pthread_num; i++)
		pthread_join(tid[i], NULL);

    // 8. 恢复光标显示
    my_show_curse();

    return 0;
}

---------- MAKEFILE
all:
	gcc mul_cp.c sub_cp.c -o xcp
clean:
	-rm xcp *.~ a.out

---------- MUL.TXT
  

  

posted @ 2012-09-17 12:57  庄庄庄  阅读(323)  评论(0编辑  收藏  举报