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