Я написал не большую программку, которая копирует файлы из одной директории в другую.
Цель: продемонстрировать преимущества многопоточности.
Но вот результаты не радуют.
Копирую 445 файлов из одной директории в другую. Общий вес файлов - 842,9 метра.
Время выполнения программы:
1 поток:
real 1m16.085s
user 0m9.097s
sys 0m3.708s
2 потока:
real 1m17.756s
user 0m9.037s
sys 0m4.208s
3 потока:
real 1m27.259s
user 0m9.141s
sys 0m4.152s
Привожу исходный код:
Код: Выделить всё
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <pthread.h>
#define MAX_NAME_LEN 100
#define MAX_DATA_LEN 100
#define THREADS_COUNT 3
struct fileAttr{
char fileName[MAX_NAME_LEN];
char dataFromFile[MAX_DATA_LEN];
};
struct dirAttr{
DIR *dp;
char copyFromDir[MAX_NAME_LEN];
char copyToDir[MAX_NAME_LEN];
};
pthread_mutex_t blockMutex = PTHREAD_MUTEX_INITIALIZER;
void *beginCopy(void *);
void setPathAndFileName(char *, const char *, const char *);
int main(int argc, char *argv[]){
struct dirAttr dAttr;
pthread_t threads[THREADS_COUNT];
int i;
if(argc != 3){
printf("Usage: %s <copy from dir> <copy to dir>\n", argv[0]);
exit(1);
}
strncpy(dAttr.copyFromDir, argv[1], sizeof(dAttr.copyFromDir));
strncpy(dAttr.copyToDir, argv[2], sizeof(dAttr.copyToDir));
// Открываем директорию от куда копировать
dAttr.dp = opendir(dAttr.copyFromDir);
if(dAttr.dp == NULL){
printf("[ERROR] Can't open dir %s\n", dAttr.copyFromDir);
exit(1);
}
// Проверяем, существует ли директория, куда копировать
// Если нет, создаём её
if(opendir(dAttr.copyToDir) == NULL)
if(mkdir(dAttr.copyToDir, S_IRUSR | S_IWUSR | S_IXUSR) == -1){
printf("[ERROR] Can't make dir %s\n", dAttr.copyToDir);
exit(1);
}
else
printf("[INFO] Directory %s does not exists. I was make it\n", dAttr.copyToDir);
for(i = 0; i < THREADS_COUNT; i++)
if(pthread_create(&threads[i], NULL, beginCopy, (void *)&dAttr) != 0)
perror("[ERROR] Can't create thread");
for(i = 0; i < THREADS_COUNT; i++)
pthread_join(threads[i], NULL);
closedir(dAttr.dp);
exit(0);
}
void *beginCopy(void *arg){
struct fileAttr fAttr;
struct dirent *dirp;
FILE *copyFrom, *copyTo;
struct dirAttr *dAttr = (struct dirAttr *)arg;
pthread_mutex_lock(&blockMutex);
// Просматриваем файлы в указанной директории
while((dirp = readdir(dAttr->dp)) != NULL){
if(!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
continue;
pthread_mutex_unlock(&blockMutex);
printf("[INFO] thread id %u\n", pthread_self());
fflush(stdout);
setPathAndFileName(fAttr.fileName, dAttr->copyFromDir, dirp->d_name);
printf("copy from: %s\n", fAttr.fileName);
fflush(stdout);
copyFrom = fopen(fAttr.fileName, "r");
if(copyFrom == NULL){
printf("[ERROR] Can't open file %s to read\n", fAttr.fileName);
continue;
}
setPathAndFileName(fAttr.fileName, dAttr->copyToDir, dirp->d_name);
printf("copy to : %s ... ", fAttr.fileName);
fflush(stdout);
copyTo = fopen(fAttr.fileName, "w");
if(copyFrom == NULL){
printf("[ERROR] Can't open file %s to write\n", fAttr.fileName);
continue;
}
// Копирование данных
while(fgets(fAttr.dataFromFile, MAX_DATA_LEN, copyFrom) != NULL)
fputs(fAttr.dataFromFile, copyTo);
printf("Done\n\n");
fflush(stdout);
fclose(copyFrom);
fclose(copyTo);
}
}
void setPathAndFileName(char *fName, const char *path, const char *name){
bzero(fName, sizeof(fName));
strncpy(fName, path, MAX_NAME_LEN);
strncat(fName, "/", 1);
strncat(fName, name, MAX_NAME_LEN);
}
Мьютексом блокируется лишь получение имени последующего файла, но копирование не блокируется.
Системный монитор показывает, что во время работы программы, кол-во открытых ею файлов = кол-во потоков * 2, т.к. каждый поток открывает файл "копировать из" и "копировать в".
По идее, при увеличении числа потоков, программа должна выполняться быстрее, но на деле происходит иначе.
Подскажите, почему так?