apue学习之多线程拷贝文件
这是一个与多线程相关的小练习,顺带可以复习文件属性,内存映射的知识,代码如下,注释详尽。
// File Name: multithread_copy.c
// Author: AlexanderGan
// Created Time: Mon 29 Jun 2020 03:41:20 PM CST
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>
#include<sys/mman.h>
#define THR_NUM 6 //线程数量
typedef struct _TaskInfo{
int num;//线程序号
void* src;//源地址
void* dst;//目的地址
int size;//文件尺寸
}TaskInfo;
void* multithread_copy(void* arg)
{
TaskInfo *info = arg;
int num = info->num;
int cpsize = info->size / THR_NUM;
int mod = info->size % cpsize;//平分后余下的部分
if (num == THR_NUM -1){
//如果是最后一个线程需要处理自己的+余下的部分
memcpy(info->dst+num*cpsize,info->src+num*cpsize,cpsize+mod);
}
else{
memcpy(info->dst+num*cpsize,info->src+num*cpsize,cpsize);
}
return NULL;
}
int main(int argc, char* argv[]){
if(argc != 3){
//如果参数不足
printf("please input srcfilename dstfilename!\n");
return -1;
}
struct stat fileinfo;//文件信息结构体apue,p75
if(stat(argv[1],&fileinfo) < 0)//stat函数获取结构体信息
{
perror("argv1 error!\n");
exit(-1);
}
long filesize = fileinfo.st_size;//获取文件大小
int srcfd = open(argv[1],O_RDONLY);
int dstfd = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0664);
ftruncate(dstfd,filesize);//文件截断,apue,p90
if(srcfd < 0 || dstfd < 0){
printf("open srcfile, dstfile error!\n");
exit(-1);
}
void* srcmem = mmap(NULL,filesize,PROT_READ,MAP_PRIVATE,srcfd,0);//源文件映射
if(srcmem == MAP_FAILED)
{
perror("mmap srcfile error!\n");
exit(-1);
}
void* dstmem = mmap(NULL,filesize,PROT_WRITE,MAP_SHARED,dstfd,0);//目标文件映射
if(dstmem == MAP_FAILED)
{
perror("mmap dstfile error!\n");
exit(-1);
}
TaskInfo tinf[THR_NUM];
pthread_t tid[THR_NUM];
int i;
for(i = 0; i < THR_NUM;i++)//把映射的地址传给线程处理
{
tinf[i].src = srcmem;
tinf[i].dst = dstmem;
tinf[i].num = i;
tinf[i].size = filesize;
pthread_create(&tid[i],NULL,multithread_copy,&tinf[i]);//线程创建,apue,p309
}
for(i = 0; i< THR_NUM;i++){
pthread_join(tid[i],NULL);//回收线程
}
close(srcfd);//关闭文件描述符
close(dstfd);
munmap(srcmem,filesize);//取消映射
munmap(dstmem,filesize);
return 0 ;
}