多进程和多线程文件拷贝

时间:2022-06-24 10:07:36
1. 线程与进程的异同点

A.相同点

1):  比如都有自己在系统中唯一标识ID,一组寄存器(pc指针 ),状态(6种),调度优先级以及所要遵循的调度策略。
2):  每个进程都有一个进程控制块,线程也拥有一个线程控制块(在Linux内核,线程控制块与进程控制块用同一个结         构体描述,即struct  task_struct),这个控制块包含线程的一些属性信息,操作系统使用这些属性信息来描述线             程。
3):  线程和子进程的创建者可以在线程和子进程上实行某些控制,比如,创建者可以取消、挂起、继续和修改线程和         子进程的优先级。

B.不同点

1): 主要区别:每个进程都拥有自己的地址空间,但线程没有自己独立的地址空间,但是线程栈是线程专属的,而是运         行在一个进程里的所有线程共享该进程的整个虚拟地址空间。
2):  线程的上下文切换时间开销比进程上下文切换时间开销要小的多
3):  线程的创建开销远远小于进程的创建
4): 子进程拥有父进程的地址空间和数据段的拷贝,因此当子进程修改它的变量和数据时,它不会影响父进程中的数         据,但线程可以直接访问它进程中的数据段。
5):  进程之间通讯必须使用进程间通讯机制,但线程可以与进程中的其他线程直接通讯
6):  线程可以对同一进程中的其他线程实施大量控制,但进程只能对子进程实施控制
7):  改变主线程的属性可能影响进程中其他的线程,但对父进程的修改不影响子进程

2. 多进程文件拷贝程序:
<pre name="code" class="cpp">#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

int copy_file_init(const char *src_file,const char *dest_file)
{
	int fd_src;
	int fd_dest;
	int src_file_len;
	
	fd_src = open(src_file,O_RDONLY);
	if(fd_src < 0){
		fprintf(stderr,"Fail to open %s : %s\n",src_file,strerror(errno));
		exit(EXIT_FAILURE);
	}

	src_file_len = lseek(fd_src,0,SEEK_END);

	fd_dest = open(dest_file,O_WRONLY | O_TRUNC | O_CREAT,0666);
	if(fd_dest < 0){
		fprintf(stderr,"Fail to open %s : %s\n",dest_file,strerror(errno));
		exit(EXIT_FAILURE);
	}
	
	close(fd_src);
	close(fd_dest);

	return src_file_len;
}

int copy_file(const char *src_file,const char *dest_file,int postion,int len)
{
	int n;
	int fd_src;
	int fd_dest;
	int count = 0;
	char buf[1024];

	fd_src = open(src_file,O_RDONLY);
	if(fd_src < 0){
		fprintf(stderr,"Fail to open %s : %s\n",src_file,strerror(errno));
		exit(EXIT_FAILURE);
	}

	fd_dest = open(dest_file,O_WRONLY);
	if(fd_dest < 0){
		fprintf(stderr,"Fail to open %s : %s\n",dest_file,strerror(errno));
		exit(EXIT_FAILURE);
	}

	lseek(fd_src,postion,SEEK_SET);
	lseek(fd_dest,postion,SEEK_SET);
	
	while(1){
		n = read(fd_src,buf,sizeof(buf));
		if(n <= 0){
			break;
		}
		
		n = write(fd_dest,buf,n);
		if(n <= 0){
			break;
		}

		count += n;

		if(count >= len){
			break;
		}
	}
	
	close(fd_src);
	close(fd_dest);

	return count;
}

void process_copy_file(const char *src_file,const char *dest_file,int src_file_len,int precess_num)
{
	int n;
	int m=0;
	pid_t pid;

	pid = fork();
	if(pid < 0){
		perror("Fail to fork");
		exit(EXIT_FAILURE);
	}

	if(pid == 0){
		n = copy_file(src_file,dest_file,src_file_len/2,(src_file_len - src_file_len / 2));
		printf("Child process copy %d bytes!\n",n);
	}

	if(pid > 0){
		n = copy_file(src_file,dest_file,0,src_file_len / 2);
		printf("Parent process copy %d bytes!\n",n);
	}
	
	while(precess_num > 0){
		pid = fork();
		if(pid < 0){
			perror("Fail to fork");
			exit(EXIT_FAILURE);
		}
		else{
			n--;
		}
		if
	}
	
	return ;
}

//./a.out src_file dest_file
int main(int argc, const char *argv[])
{
	int src_file_len;

	if(argc < 3){
		fprintf(stderr,"Usage : %s <src file> <dest file>!\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	src_file_len = copy_file_init(argv[1],argv[2]);
	process_copy_file(argv[1],argv[2],src_file_len);
	exit(EXIT_SUCCESS);
		
}


 
 
 
3. 多线程文件拷贝程序:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>


//pthread_mutex_t lock;
struct args{
char src_file[128];
char des_file[128];
int position;
int len;
};


int get_filelen(const char *src_file)
{
int len; 
FILE *fp;
fp = fopen(src_file,"r");
fseek(fp,0,SEEK_END);
len = ftell(fp);
rewind(fp);
return len;
}


void init_args(struct args *args ,const char *src_file,const char *des_file,int pos,int len)
{
strcpy(args->src_file, src_file);
strcpy(args->des_file, des_file);
args->position = pos;
args->len = len;
}


void *copy_file(void *arg)
{
// pthread_mutex_lock(&lock);
int n = 0;
int ret;
int count = 0;
int read_len = 0;
char buf[4096];
FILE *fp1,*fp2;
struct args *p = (struct args*)arg;
fp1 = fopen(p->src_file,"r");
if(fp1 == NULL){
fprintf(stderr,"fopen file %s fail:%s\n",p->src_file,strerror(errno));
exit(EXIT_FAILURE);
}

fp2 = fopen(p->des_file,"a");
if(fp2 == NULL){
fprintf(stderr,"fopen file %s fail:%s\n",p->des_file,strerror(errno));
exit(EXIT_FAILURE);
}


fseek(fp1,p->position,SEEK_SET);
fseek(fp2,p->position,SEEK_SET);
printf("p->position=%d,p->len=%d\n",p->position,p->len);
read_len = p->len > 4096?4096:p->len;

while(1){
if(count >= p->len){
break; 
}
printf("read_len=%d\n",read_len);
n = fread(buf,sizeof(buf[0]),read_len,fp1);
if(n <= 0){
printf("fread over: %d\n",n);
break; 
}
printf("n=%d\n",n);
ret = fwrite(buf,sizeof(buf[0]),n,fp2);
if(ret <= 0){
printf("fwrite over\n");
break; 
}
count += n;
}
printf("write %d bytes to des file\n",count);


fclose(fp1);
fclose(fp2);
// pthread_mutex_unlock(&lock);
}


int main(int argc, const char *argv[])
{
int ret;
int len;
int position;
struct args args1,args2;
pthread_t tid1,tid2;


//pthread_mutex_init(&lock,NULL);


if(argc < 3){
fprintf(stderr,"Usage: %s <filename> <filename>\n",argv[0]);
exit(EXIT_FAILURE);
}


len = get_filelen(argv[1]);
position = len / 2;
init_args(&args1,argv[1],argv[2],0,position);
init_args(&args2,argv[1],argv[2],position,len-position);
fprintf(stdout,"src file length=%d\n",len);


ret = pthread_create(&tid1,NULL,copy_file,&args1);
if(ret != 0){
fprintf(stderr,"create pthread tid1 fail: %s\n",strerror(errno));
exit(EXIT_FAILURE);
}




ret = pthread_create(&tid2,NULL,copy_file,&args2);
if(ret != 0){
fprintf(stderr,"create pthread tid2 fail: %s\n",strerror(errno));
exit(EXIT_FAILURE);
}


pthread_join(tid1,NULL);
pthread_join(tid2,NULL);


}