#include "apue.h" #include <fcntl.h> #include <pthread.h> void * copyFile(void *); // 创建空的文件 int createFile(int fd, int size); /** 确定文件所属的大小范围,根据这个大小范围确定拷贝子进程的数目 * * 返回值 1 ------- 文件大小小于10K, 1个拷贝子进程用于拷贝该文件 * 2 ------- 文件大小小于1M, 2个拷贝子进程用于拷贝该文件 * 4 ------- 文件大小小于128M, 4个拷贝子进程用于拷贝该文件 * 8 ------- 文件大小大于128M, 8个拷贝子进程用于拷贝该文件 */ int getThdNum(int flSz); /** * 每个线程的信息 * */ struct td_inf { int index; // 进程的索引 pthread_t thread_ID;// 该线程的ID int fdsr; // 源文件的文件描述符 int fdds; // 目标文件的文件描述符 int start; // 源文件的开始位置 int end; // 源文件的结束位置 int blockSize; // 每块的大小, 每个块大小为1024* 1024 int blockNum; // 块的个数 int rd_cur; int wt_cur; }; struct td_inf** tds; // 指向td_inf数组的指针 pthread_mutex_t rd_lock; pthread_mutex_t wt_lock; int blkSize; // 定义一块的大小 #define BLKSZ_G 1024 * 1024 * 1024 #define BLKSZ_128M 128 * 1024* 1024 #define BLKSZ_M 1024 * 1024 #define BLKSZ_16K 16 * 1024 #define BLKSZ_8K 8 * 1024 int main(int argc, char *argv[]) { int srflSize; off_t start, end; int fdsr, fdds; int i; struct td_inf* tids; // 指向td_inf的指针 int thdNum; if (argc != 3) { err_sys("param error"); } // 打开源文件 if((fdsr = open(argv[1], O_RDONLY, O_SYNC)) < 0) { err_sys("open source file %s error", argv[1]); } // 打开目标文件 if((fdds = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, O_SYNC)) < 0) { err_sys("open dest file %s error", argv[2]); } // 获得源文件的大小 start = lseek(fdsr, 0, SEEK_SET); if(start == 1) { close(fdsr); close(fdds); err_sys("lseek err"); } end = lseek(fdsr, 0, SEEK_END); if(end == 1) { close(fdsr); close(fdds); err_sys("lseek err"); } srflSize = (end - start); printf("file size is %dbyte/n", srflSize); createFile(fdds, srflSize); // 创建和源文件一样大小的目标文件 printf("%d/n", srflSize); thdNum = getThdNum(srflSize); printf("thdNum = %d/n", thdNum); // return 0; // blkSize = 1024 * 1024; blkSize = srflSize / thdNum + 1; printf("blkNum = %d /n", blkSize); if (pthread_mutex_init(&rd_lock, NULL) != 0) { err_sys("thread mutex init error"); } if (pthread_mutex_init(&wt_lock, NULL) != 0) { err_sys("thread mutex init error"); } // 创建blkNum个空间,来存储每一个线程 tds = (struct td_inf**)malloc(sizeof(struct td_inf*) * thdNum); if(tds == NULL) { close(fdsr); close(fdds); err_sys("malloc thread information err"); } // 创建前N - 1 个线程 for(i = 0;i < thdNum ; i++) { tids = (struct td_inf*)malloc(sizeof(struct td_inf)); if(tids == NULL) { close(fdsr); close(fdds); err_sys("malloc thread information err"); } tids->index = i; tids->start = i * blkSize; // 开始位置 tids->rd_cur = tids->wt_cur = 0; // 当前位置,这个值是相对于开始位置来说的 if(i == thdNum -1) tids->end = end; else tids->end = (i + 1) * blkSize - 1; tids->fdsr = fdsr; tids->fdds = fdds; tds[i] = tids; if(pthread_create(&(tids->thread_ID),NULL,copyFile, tids) != 0) { close(fdsr); close(fdds); err_sys("create thread %d error", i); } tids = NULL; } for(i = 0; i < thdNum; i++) { if(pthread_join(tds[i]->thread_ID, NULL) != 0) { close(fdsr); close(fdds); err_sys("join thread %d error", i); } } for(i = 0; i < thdNum; i++) { if(tds[i] != NULL) free(tds[i]); } if(tds != NULL) { free(tds); } close(fdsr); close(fdds); return 0; } void * copyFile(void * tidInf) { struct td_inf* tids; int fdds; int fdsr; int start; int end; int bufSize = 1024; char buf[1024]; int ret; int rd_cur; int wt_cur; tids = (struct td_inf* )tidInf; fdds = tids->fdds; fdsr = tids->fdsr; start =tids->start; end = tids->end; // 磁盘读写 while (1) { pthread_mutex_lock(&rd_lock); rd_cur = tids->rd_cur; if(lseek(fdsr, start + rd_cur, SEEK_SET) == -1) { close(fdds); close(fdsr); err_sys("lseek error"); } if((ret = read(fdsr, buf, bufSize)) == -1) // 读写出错 { //pthread_mutex_unlock(&rd_lock); continue; } if(ret == 0) // 文件结束 { break; } tids->rd_cur = lseek(fdsr, 0, SEEK_CUR); pthread_mutex_unlock(&rd_lock); pthread_mutex_lock(&wt_lock); wt_cur = tids->wt_cur; if(lseek(fdds, start + wt_cur, SEEK_SET) == -1) { close(fdds); close(fdsr); err_sys("lseek error"); } if(write(fdds, buf, bufSize) == -1) { err_sys("write error/n"); } tids->wt_cur = lseek(fdds, 0, SEEK_CUR); pthread_mutex_unlock(&wt_lock); } if(ret == 0) { pthread_mutex_unlock(&rd_lock); } /* while((ret = read(fdsr, buf, bufSize)) != 1) // 读写出错 { if(ret == 0) // 文件结束 { printf(buf); break; } if(write(fdds, buf, bufSize) == 1) { err_sys("write error/n"); } // tids->current = lseek(fdsr, 0, SEEK_CUR) - tids->start; } */ printf("tid.index = %d/n", tids->index); printf("tids.start = %d/n", tids->start); printf("tids.end = %d/n", tids->end); printf("tids.fdsr = %d/n", tids->fdsr); printf("tids.fdds = %d/n", tids->fdds); printf("******************************/n"); //pthread_mutex_unlock(&rd_lock); return NULL; } int createFile(int fd, int size) { int i; int bufSize = 1024 * 1024; char buf[1024 * 1024]; int blckNum; int lstBlckSz; for (i = 0;i < bufSize; i++) { buf[i]= ' '; } blckNum = size / (1024 * 1024); lstBlckSz= size - blckNum * 1024* 1024; for(i = 0;i < blckNum; i++) { write(fd, buf, bufSize); } return 0; } //#define BLKSZ_G 1024 * 1024 * 1024 //#define BLKSZ_128M 128 * 1024* 1024 //#define BLKSZ_M 1024 * 1024 //#define BLKSZ_16k 16 * 1024 //#define BLKSZ_8k 8 * 1024 int getThdNum(int flSz) { int thdNum = 0; if(flSz > BLKSZ_128M) { blkSize = BLKSZ_128M; thdNum = 8; }else if(flSz > BLKSZ_M) { blkSize = BLKSZ_M; thdNum = 4; }else if(flSz > BLKSZ_16K) { blkSize = BLKSZ_16K; thdNum = 2; } else { blkSize = flSz; thdNum = 1; } return thdNum; }