Я хочу создать копировщик файлов, используя парадигму синхронизации 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