---------- 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