C Reader Writer Мьютексы для копирования файла с использованием общей памяти и кольцевого буфера - PullRequest
0 голосов
/ 23 мая 2019

Я хочу создать копировщик файлов, используя парадигму синхронизации Reader-Writer. Писатель инициализирует оба мьютекса. FullMutex обозначает, сколько буферов доступно для записи, а FreeMutex обозначает, сколько буферов доступно для чтения. Писатель ждет, когда Блок заполнен. WritePointer и ReadPointer используют кольцевой буфер. Поэтому я использовал Mod Operation. Размер блока = M. Размер буфера = B. Есть N количество буферов. Итак, М = Н * Б. Размер файла = 2M. И поэтому BufferCount фактически продвигает File Pointer. Когда все байты записаны, я выдаю FileEnding = 1.

Команды компиляции-

g++ Writer.c -o Writer -lpthread -lrt
g++ Reader.c -o Reader -lpthread -lrt

А в двух разных командных приглашениях открыты и команды выдаются -

./Writer
./Reader

Теперь я не знаю, почему это не копирование, и не знаю, как использовать sem_post.
Вот писатель.c

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

int main(void){
    struct MemData{
        sem_t FullMutex;
        sem_t FreeMutex;
        char FileName[128];
        int ReadPointer;
        int WritePointer;
        int FileEnding;
        char Data[512000];//MEMORY BLOCK SIZE: 500 KB
    };
    int SD;
    struct MemData *M;
    int NumberOfBuffers=10;
    //int BufferSize=51200;//FILE BUFFER SIZE 50 KB
    int BufferSize=2;//EXPERIMENATION
    unsigned char Buf[BufferSize];
    int BufferCount=0;

    SD= shm_open("/program.shared", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
    if(SD< 0){
        printf("\nshm_open() error \n");
        return EXIT_FAILURE;
    }
    fchmod(SD, S_IRWXU|S_IRWXG|S_IRWXO);
    if(ftruncate(SD, sizeof(MemData))< 0){
        printf ("ftruncate() error \n");
        return EXIT_FAILURE;
    }
    M=(struct MemData*)mmap(NULL, sizeof(MemData), PROT_READ|PROT_WRITE, MAP_SHARED, SD, 0);
    if(M== MAP_FAILED){
        printf("mmap() error");
        return EXIT_FAILURE;
    }else{
        sem_init(&M->FullMutex, 1, 0);
        sem_init(&M->FreeMutex, 1, NumberOfBuffers);
        strcpy(M->FileName, "aaa.txt");
        M->FileEnding=0;
        M->ReadPointer=0;
        M->WritePointer=0;
        memset(M->Data, '\0', strlen(M->Data));
    }
    char FileName[128]="aaa.txt";
    FILE *FP= fopen(FileName, "rb");
    if(FP!= NULL){
        struct stat StatBuf;
        if(stat(FileName, &StatBuf)==-1){
            printf("failed to fstat %s\n", FileName);
            exit(EXIT_FAILURE);
        }
        long long FileSize=StatBuf.st_size;
        printf("\nFile Size: %lld", FileSize);
        long long FilePosition=ftell(FP);
        FilePosition=ftell(FP);
        long long CopyableMemorySize=FileSize-FilePosition;
        printf("\nCopyable File Size: %lld", CopyableMemorySize);
        int NumberOfFileBuffers=CopyableMemorySize/BufferSize;
        printf("\n Number Of File Buffers: %d", NumberOfFileBuffers);
        while(1){
            sem_wait(&M->FreeMutex);
            fseek(FP, BufferCount*BufferSize, SEEK_SET);
            fread(Buf, sizeof(unsigned char), BufferSize, FP);
            int FreeMutexValue;
            sem_getvalue(&M->FreeMutex, &FreeMutexValue);
            int FullMutexValue;
            sem_getvalue(&M->FullMutex, &FullMutexValue);
            printf("\nMutexes-Free: %d and Full: %d", FreeMutexValue, FullMutexValue);
            printf("\nBuffer Writing: %s", BufferCount);
            memcpy(&M->Data[M->WritePointer*BufferSize], &Buf, sizeof(Buf)*sizeof(unsigned char));
            BufferCount++;
            M->WritePointer=(M->WritePointer+1)%NumberOfBuffers;
            if(BufferCount>=NumberOfFileBuffers && M->WritePointer==M->ReadPointer){
                M->FileEnding=1;
                break;
            }
            sem_post(&M->FullMutex);
        }
        fclose(FP);
    }
    close(SD);
    return 0;
}

Считыватель использует мьютекс, открытый Writer.c. Все размеры блока, размер буфера и количество буферов такие же, как Writer.c. Когда Reader получает FileEnding == 1, он прерывает цикл, поскольку нечего обрабатывать. Читатель уничтожает мьютекс и освобождает память.

Вот читатель.c

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

int main(void){
    char FileName[128]="bbb.txt";
    struct MemData{
        sem_t FullMutex;
        sem_t FreeMutex;
        char FileName[128];
        int ReadPointer;
        int WritePointer;
        int FileEnding;
        char Data[512000];//MEMORY BLOCK SIZE: 500 KB
    };
    int SD;
    struct MemData *M;
    int NumberOfBuffers=10;
    //int BufferSize=51200;//FILE BUFFER SIZE 50 KB
    int BufferSize=2;//EXPERIMENATION
    unsigned char Buf[BufferSize];
    int BufferCount=0;
    SD= shm_open("/program.shared", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
    if(SD< 0){
        printf("\nshm_open() error \n"); 
        return EXIT_FAILURE; 
    }
    M=(struct MemData*)mmap(NULL, sizeof(MemData), PROT_READ|PROT_WRITE, MAP_SHARED, SD, 0);
    if(M== MAP_FAILED){
        printf("mmap() error");
        return EXIT_FAILURE;
    }

    FILE *FP= fopen(FileName, "wb");
    if(FP!= NULL){
        while(1){
            sem_wait(&M->FullMutex);
            int FreeMutexValue;
            sem_getvalue(&M->FreeMutex, &FreeMutexValue);
            int FullMutexValue;
            sem_getvalue(&M->FullMutex, &FullMutexValue);
            printf("\nMutexes-Free: %d and Full: %d", FreeMutexValue, FullMutexValue);
             printf("\nBuffer Writing: %d", BufferCount);
            printf("\nReadPointer: %d", M->ReadPointer);
            printf("\nWritePointer: %d", M->WritePointer);
            fseek(FP, BufferCount*BufferSize, SEEK_SET);
            fseek(FP, BufferCount*BufferSize, SEEK_SET);
            fwrite(&M->Data[M->ReadPointer*BufferSize], sizeof(unsigned char), BufferSize, FP);
            BufferCount++;
            M->ReadPointer=(M->ReadPointer+1)%NumberOfBuffers;
            if(M->FileEnding){
                fclose(FP);
                break;
            }
            sem_post(&M->FreeMutex);
        }
    }
    munmap(M,sizeof(MemData));
    close(SD);
    return 0;
}

Входной файл (aaa.txt) содержит эти строки-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Выходной файл (bbb.txt) содержит эти строки-

1
2
3
4
5
6
7
8
9
10
11
12
13
14    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...