如果代码难理解,欢迎多交流一下
实现功能
多线程拷贝命令,如:./my_cp srcfile destfile N(拷贝线程个数)
- mmap将磁盘文件映射到内存空间
- pthread_create创建线程
- pthread_detach将子线程分离,好处:线程不需在主线程中pthread_join进行阻塞回收资源,子线程结束后由系统自动回收。
- Info为自定义结构体,用于线程调用函数的传参,参数包括文件大小、srcfile的内存地址指针、descfile的内存地址指针、最大线程数以及当前为第几个线程标志。
Info描述符(结构体)
// An highlighted block
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void sys_err(char *str)
{
perror(str);
exit(1);
}
typedef struct Info{
int maxnum;//最大线程数
int num;//表示第几个线程
char *sc_addr,*desc_addr;//映射后的地址
int size;//每个线程拷贝的大小
int filesize;//文件大小
}Info;
void *thr_fn(void *arg)
{
if(arg == NULL)
sys_err("arg");
//接收参数
Info *accept = (Info *)arg;
printf("pthread %d is copying\n",accept->num);
//根据每个线程中Num成员得不同的偏移量
char offset = accept->num * accept->size;
if(accept->num < accept->maxnum-1)
memcpy(accept->desc_addr + offset,accept->sc_addr + offset,\
(size_t)accept->size);
else{
/*因为filesize/num不可能整除,所有最后一个线程需特殊处理,拷贝剩余字节,
文件总大小注意maxnum要减一,因为线程个数是从1开始,而编号是从0开始。*/
memcpy(accept->desc_addr + offset,accept->sc_addr + offset,\
(size_t)(accept->filesize - (accept->maxnum-1) * accept->size));
}
}
int main(int argc,char *argv[])
{
pthread_t tid;
Info *info;
unsigned char i;
//注意区分num 和 info->num。
int num = atoi(argv[3]);
info = (Info *)malloc(num * sizeof(Info));
memset(info,0,num * sizeof(Info));
int sc_fd = open(argv[1],O_RDONLY);
umask(0);
int desc_fd = open(argv[2],O_RDWR | O_CREAT,0777);
info[0].maxnum = num;
//通过lseek指定目标文件的大小与源文件大小一样
info[0].filesize = lseek(sc_fd,0,SEEK_END);
ftruncate(desc_fd,info[0].filesize);
//这里提醒一下,5个线程对应的Info结构体参数只有num成员不同,其它均一样。
info[0].size = info[0].filesize / num + (info[0].filesize % num >0? 1:0);
info[0].sc_addr = (char *)mmap(NULL, (size_t)info[0].filesize, \
PROT_READ,MAP_SHARED, sc_fd,0);
info[0].desc_addr = (char *)mmap(NULL, (size_t)info[0].filesize,\
PROT_READ | PROT_WRITE,MAP_SHARED, desc_fd, 0);
for(i = 1;i<5;i++){
info[i] = info[0];
}
while(num--){
info[num].num = num;
pthread_create(&tid,NULL,thr_fn,(void *)&info[num]);
//分离线程
pthread_detach(tid);
}
printf("main thread ending!\n");
pthread_exit(NULL);
}