Есть ли способ прочитать текстовый файл побайтно асинхронно с потоками POSIX? - PullRequest
0 голосов
/ 22 декабря 2018

Я пытаюсь прочитать и скопировать его содержимое в другой файл асинхронно с потоками POSIX в C. Предполагая, что файл содержит «aabbcc», и у меня есть 4 потока, как я могу скопировать «aabbcc» в другой файл с потоками асинхронно в CЭта часть застряла в моей голове на весь день.То, что я сделал до сих пор, показано ниже.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <aio.h>
#include <math.h> //for ceil() and floor()
#include <sys/types.h>
#include <unistd.h>

#define FILE_SIZE 1024 //in bytes

//>cc code.c -o code.out -lrt -lpthread
//>./code.out

char alphabets[52] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
                    'p','q','r','s','t','u','v','w','x','y','z',
                    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
                    'P','Q','R','S','T','U','V','W','X','Y','Z'};

long prepareInputFile(char* filename)
{
    FILE *fp;
    fp = fopen(filename, "w");
    if(fp == NULL)
    {
        printf("Cannot write to input file\n");
        return;
    }
    int index;
    char str[FILE_SIZE];
    int rand_size = (rand() % 1024)+1;
for(index = 0;index < rand_size;index++) /*Generate the file with random sizes in bytes*/
{
    int num2 = (rand() % 52); /*Get a random char in char array*/
    putc(alphabets[num2],fp); /*Write that char to the file pointed to by fp*/
}
putc('\n',fp);
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
return size;
}
//Perform main operation inside this function
void *writeToFileAsync(void *src_file, void *dest_file, 
                       void *thread, void *t_count, void *filesize)
{
    int readfd, writefd;
    struct aiocb aio_write, aio_read;
    memset(&aio_read, 0, sizeof(aio_read));
    aio_read.aio_fildes = readfd;
    aio_read.aio_nbytes = (int)filesize/(int)t_count;
    readfd = open((char *)src_file, O_RDONLY);
    if(readfd < 0)
    {
        printf("Cannot open the file for reading\n");
    }
    memset(&aio_write, 0, sizeof(aio_write));
    aio_read.aio_fildes = writefd;
    aio_read.aio_nbytes = (int)filesize/(int)t_count;
    writefd = open((void *)dest_file, O_CREAT | O_WRONLY);
    if(writefd < 0)
    {
        printf("Cannot open the file for writing\n");
    }
    return;
}
int main(int argc, char *argv[])
{
int i,threadCount;
char sourcePath[100], destPath[100];
strcpy(sourcePath,argv[1]);
if(strcmp(sourcePath, "-") == 0)
{
    getcwd(sourcePath, sizeof(sourcePath));
    strcpy(sourcePath, strcat(sourcePath, "/source.txt"));
}
else
{
    strcpy(sourcePath, strcat(sourcePath, "source.txt"));
}   
printf("Source path is: %s\n", sourcePath);
strcpy(destPath,argv[2]);
if(strcmp(destPath, "-") == 0)
{
    getcwd(destPath, sizeof(destPath));
    strcpy(destPath, strcat(destPath, "/destination.txt"));
}
else
{
    strcpy(destPath, strcat(destPath, "destination.txt"));
}
printf("Dest path is: %s\n", destPath);
threadCount = strtol(argv[3],NULL,10);
long file_size = prepareInputFile(sourcePath);
pthread_t threads[threadCount];
for(i=0;i<threadCount;i++)
{
    pthread_create(&threads[i],NULL,(void *)writeToFileAsync, NULL);
}
return 0;
}

Любая помощь будет оценена.

1 Ответ

0 голосов
/ 22 декабря 2018

Маловероятно, что распараллеливание этой операции поможет, так как оно, вероятно, связано с вводом-выводом, а не с временем ЦП, и копирование таким образом, безусловно, не будет быстрее, чем простое копирование с помощью системного вызова.

ОднакоЕсли вы хотите сделать это, один из методов будет: отобразить входной файл в память (с mmap() или эквивалентным), создать целевой буфер или файл с отображением в памяти, разделить исходный и целевой файлы на равные фрагменты, иПусть каждый поток скопирует свой фрагмент файла.Вы можете использовать memcpy(), но современный компилятор может увидеть, что делает ваш цикл, и оптимизировать его.

Даже это не так быстро, как чтение или отображение исходного файла в буфер, а затем записьон возвращается из того же буфера с write().Если все, что вам нужно сделать, это скопировать файл на диск, вам вообще не нужно копировать байты.На самом деле, вы можете даже создать вторую ссылку на файл на диске.

Это, вероятно, будет работать лучше, если срезы будут выровнены по границам страницы.Будьте очень осторожны при записи двух потоков в одну и ту же строку кэша, так как это создает условие гонки.

...