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