Linux 线程并发拷贝,【Linux】线程并发拷贝程序

#include

#include

#include

#include//输出文件信息

#include//推断是否目录

#include//使用线程

char *source_arr[512];//存放源文件路径的数组

char *destination_arr[512];//存放目标文件路径的数组

int source_arr_index=0;//存放源文件路径的数组的索引,就是for(int i=xx;..;..)那个i

int destination_arr_index=0;//存放目标文件路径的数组的索引

pthread_mutex_t mutex;//声明一个相互排斥锁mutex

int i=0;//多个线程函数用到这个i。用于记录是否复制完毕,因此作为全局变量处理~

/*字符串处理函数*/

int endwith(char* s,char c){//用于推断字符串结尾是否为“/”与“.”

if(s[strlen(s)-1]==c){

return 1;

}

else{

return 0;

}

}

char* str_contact(char* str1,char* str2){//字符串连接

char* result;

result=(char*)malloc(strlen(str1)+strlen(str2)+1);//str1的长度+str2的长度+\0;

if(!result){//假设内存动态分配失败

printf("字符串连接时,内存动态分配失败\n");

exit(1);

}

strcat(result,str1);

strcat(result,str2);//字符串拼接

return result;

}

/*遍历函数*/

int is_dir(char* path){//推断是否是目录

struct stat st;

stat(path,&st);

if(S_ISDIR(st.st_mode)){

return 1;

}

else{

return 0;

}

}

void read_folder(char* source_path,char *destination_path){//复制目录

if(!opendir(destination_path)){

if (mkdir(destination_path,0777))//假设不存在就用mkdir函数来创建

{

printf("创建目录失败。");

}

}

char *path;

path=(char*)malloc(512);//相当于其他语言的String path="",纯C环境下的字符串必须自己管理大小,这里为path直接申请512的位置的空间。用于目录的拼接

path=str_contact(path,source_path);//这三句,相当于path=source_path

struct dirent* filename;

DIR* dp=opendir(path);//用DIR指针指向这个目录

while(filename=readdir(dp)){//遍历DIR指针指向的目录,也就是文件数组。

memset(path,0,sizeof(path));

path=str_contact(path,source_path);

//假设source_path,destination_path以路径分隔符结尾。那么source_path/,destination_path/直接作路径就可以

//否则要在source_path,destination_path后面补个路径分隔符再加文件名称,谁知道你传递过来的參数是f:/a还是f:/a/啊?

char *file_source_path;

file_source_path=(char*)malloc(512);

file_source_path=str_contact(file_source_path,source_path);

if(!endwith(source_path,'/')){

file_source_path=str_contact(source_path,"/");

}

char *file_destination_path;

file_destination_path=(char*)malloc(512);

file_destination_path=str_contact(file_destination_path,destination_path);

if(!endwith(destination_path,'/')){

file_destination_path=str_contact(destination_path,"/");

}

//取文件名称与当前目录拼接成一个完整的路径

file_source_path=str_contact(file_source_path,filename->d_name);

if(is_dir(file_source_path)){//假设是目录

if(!endwith(file_source_path,'.')){//同一时候并不以.结尾,由于Linux在全部目录都有一个.目录用于连接上一级目录,必须剔除,否则进行递归的话,后果无法想象!

file_destination_path=str_contact(file_destination_path,filename->d_name);//对目标目录的处理。取文件名称与当前目录拼接成一个完整的路径

read_folder(file_source_path,file_destination_path);//进行递归调用,相当于进入这个目录进行遍历~

}

}

else{//否则。将源文件于目标文件的路径分别存入相关数组

//对目标目录的处理,取文件名称与当前目录拼接成一个完整的路径

file_destination_path=str_contact(file_destination_path,"前缀_");//给目标文件重命名,这里示意怎样加个前缀~^_^

file_destination_path=str_contact(file_destination_path,filename->d_name);

source_arr[source_arr_index]=file_source_path;

source_arr_index++;

destination_arr[destination_arr_index]=file_destination_path;

destination_arr_index++;

}

}

}

/*复制函数*/

void copy_file(char* source_path,char *destination_path){//拷贝文件

char buffer[1024];

FILE *in,*out;//定义两个文件流。分别用于文件的读取和写入int len;

if((in=fopen(source_path,"r"))==NULL){//打开源文件的文件流

printf("源文件打开失败!\n");

exit(1);

}

if((out=fopen(destination_path,"w"))==NULL){//打开目标文件的文件流

printf("目标文件创建失败!\n");

exit(1);

}

int len;//len为fread读到的字节长

while((len=fread(buffer,1,1024,in))>0){//从源文件里读取数据并放到缓冲区中。第二个參数1也能够写成sizeof(char)

fwrite(buffer,1,len,out);//将缓冲区的数据写到目标文件里

}

fclose(out);

fclose(in);

}

/*线程运行函数*/

void *thread_function(void *arg){

while(i

if(pthread_mutex_lock(&mutex)!=0){//对相互排斥锁上锁,临界区開始

printf("%s的相互排斥锁创建失败。\n",(char *)arg);

pthread_exit(NULL);

}

if(i

copy_file(source_arr[i],destination_arr[i]);//复制单一文件

printf("%s复制%s到%s成功!

\n",(char *)arg,source_arr[i],destination_arr[i]);

i++;

sleep(1);//该线程挂起1秒

}

else{//否则退出

pthread_exit(NULL);//退出线程

}

pthread_mutex_unlock(&mutex);//解锁,临界区结束

sleep(1);//该线程挂起1秒

}

pthread_exit(NULL);//退出线程

}

/*主函数*/

int main(int argc,char *argv[]){

if(argv[1]==NULL||argv[2]==NULL){

printf("请输入两个目录路径,第一个为源。第二个为目的!

\n");

exit(1);

}

char* source_path=argv[1];//取用户输入的第一个參数

char* destination_path=argv[2];//取用户输入的第二个參数

DIR* source=opendir(source_path);

DIR* destination=opendir(destination_path);

if(!source||!destination){

printf("你输入的一个參数或者第二个參数不是目录!\n");

}

read_folder(source_path,destination_path);//进行目录的遍历

/*线程并发開始*/

pthread_mutex_init(&mutex,NULL);//初始化这个相互排斥锁

//声明并创建三个线程

pthread_t t1;

pthread_t t2;

pthread_t t3;

if(pthread_create(&t1,NULL,thread_function,"线程1")!=0){

printf("创建线程失败!程序结束!

\n");

exit(1);

}

if(pthread_create(&t2,NULL,thread_function,"线程2")!=0){

printf("创建线程失败!

程序结束。\n");

exit(1);

}

if(pthread_create(&t3,NULL,thread_function,"线程3")!=0){

printf("创建线程失败!

程序结束!\n");

exit(1);

}

pthread_join(t1,NULL);

pthread_join(t2,NULL);

pthread_join(t3,NULL);

//三个线程都完毕才干运行下面的代码

pthread_mutex_destroy(&mutex);//销毁这个相互排斥锁

/*线程并发结束*/

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值