Linux C语言多线程大文件拷贝代码

Linux C多线程大文件拷贝代码,自己练习写的,留做纪念!

方法1:read、write实现

该方法下,由于read、write是两个系统调用,很有可能T1 read完,未来及write就失去了CPU资源,T2获取CPU进行读写操作后,T1再次获得CPU,

从而写至错误位置上。为避免该种情况,只能在每次读写之前修改文件读写位置。但lseek和read这两个系统调用间也可能失去CPU。

必须合为一个原子操作。pread、pwrite可实现该目的。

方法2:mmap实现

使用mmap将待拷贝文件映射至内存。创建T1、T2两个线程,一个线程负责拷贝上半区域,另一个线程拷贝下半区域。

由于被实现成数组,T1、T2之间没有交集部分,可做各自拷贝。只需划分拷贝位置即可。

#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>

typedef struct{
	int off;
	int size;
}arg_t;

char *s, *d;

void *tfn(void *arg)
{
	arg_t *p; int i;

	p = (arg_t *)arg;

	for (i = 0; i < p->size; i++)
		d[p->off+i] = s[p->off+i];

	return NULL;
}
#if 0
int main(int argc, char *argv[])
{
	int n = 5, i, off, size;
	int in, out;
	struct stat statbuf;
	pthread_t *tid;
	arg_t *p;

	if (argc == 4)
		n = atoi(argv[3]);

	in = open(argv[1], O_RDONLY);
	if (in == -1) {
		perror("open src error");
		exit(1);
	}
	out = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0644);
	if (in == -1) {
		perror("open dst error");
		exit(1);
	}
	if (stat(argv[1], &statbuf) == -1) {
		perror("stat error");
		exit(1);
	}

	lseek(out, statbuf.st_size-1, SEEK_SET);
	write(out, "a", 1);

	s = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, in, 0);
	if (s == MAP_FAILED) {
		perror("mmap src error");
		exit(1);
	}
	d = mmap(NULL, statbuf.st_size, PROT_WRITE, MAP_SHARED, out, 0);
	if (d == MAP_FAILED) {
		perror("mmap dst error");
		exit(1);
	}
	close(in); close(out);

	tid = malloc(sizeof(pthread_t)*n);
	if (tid == NULL) {
		printf("tid malloc fail\n");
		exit(1);
	}
	p = malloc(sizeof(arg_t)*n);
	if (p == NULL) {
		printf("p malloc fail\n");
		exit(1);
	}

	size = statbuf.st_size / n;
	for (i = 0, off = 0; i < n; i++, off += size) {
		p[i].off = off;
		p[i].size = size;
	}
	p[n-1].size += statbuf.st_size % n;	

	for (i = 0; i < n; i++) 
		pthread_create(&tid[i], NULL, tfn, (void *)&p[i]);

	for (i = 0; i < n; i++) 
		pthread_join(tid[i], NULL);

	munmap(s, statbuf.st_size);
	munmap(d, statbuf.st_size);

	return 0;
}

#else
int main(int argc, char *argv[])
{
	int n = 5, i, off, size;
	int in, out;
	struct stat statbuf;
	pthread_t *tid;
	arg_t *p;

	if (argc == 4)
		n = atoi(argv[3]);

	in = open(argv[1], O_RDONLY);
	out = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0644);
	stat(argv[1], &statbuf);

	lseek(out, statbuf.st_size-1, SEEK_SET);
	write(out, "a", 1);

	s = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, in, 0);
	d = mmap(NULL, statbuf.st_size, PROT_WRITE, MAP_SHARED, out, 0);
	close(in); close(out);

	tid = malloc(sizeof(pthread_t)*n);
	p = malloc(sizeof(arg_t)*n);

	size = statbuf.st_size / n;
	for (i = 0, off = 0; i < n; i++, off += size) {
		p[i].off = off;
		p[i].size = size;
	}
	p[n-1].size += statbuf.st_size % n;	/*最后一个线程包圆*/

	for (i = 0; i < n; i++) 
		pthread_create(&tid[i], NULL, tfn, (void *)&p[i]);

	for (i = 0; i < n; i++) 
		pthread_join(tid[i], NULL);

	munmap(s, statbuf.st_size);
	munmap(d, statbuf.st_size);

	return 0;
}

#endif

 

庄朋龙
庄朋龙

一个爱生活的技术菜鸟

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注