- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想使用 Reader-Writer Synchronization Paradigm 构建一个文件复制器。
Writer 初始化这两个互斥锁。 FullMutex 表示有多少 Buffer 可供写入,而 FreeMutex 表示有多少 Buffer 可供读取。
当 Block 已满时,Writer 等待。
WritePointer 和 ReadPointer 正在使用 Ring Buffer。因此我使用了Mod Operation。
block 大小=M。
缓冲区大小=B。
有 N 个 Buffer。
所以,M=N*B。
文件大小=2M。
因此 BufferCount 实际上是在推进文件指针。
写入所有字节后,我发出 FileEnding=1。
编译命令是 -
g++ Writer.c -o Writer -lpthread -lrt
g++ Reader.c -o Reader -lpthread -lrt
./Writer
./Reader
#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]="aaa.txt";
struct MemData{
sem_t FullMutex;
sem_t FreeMutex;
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);
M->FileEnding=0;
M->ReadPointer=0;
M->WritePointer=0;
memset(M->Data, '\0', strlen(M->Data));
}
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("\nNumber Of File Buffers: %d\n", NumberOfFileBuffers);
//WRITE
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: %d", 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;
}
#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;
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){
//READ
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);
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;
}
File Size: 50
Copyable File Size: 50
Number Of File Buffers: 25
Mutexes-Free: 9 and Full: 0
Buffer Writing: 0
Mutexes-Free: 8 and Full: 1
Buffer Writing: 1
Mutexes-Free: 7 and Full: 2
Buffer Writing: 2
Mutexes-Free: 6 and Full: 3
Buffer Writing: 3
Mutexes-Free: 5 and Full: 4
Buffer Writing: 4
Mutexes-Free: 4 and Full: 5
Buffer Writing: 5
Mutexes-Free: 3 and Full: 6
Buffer Writing: 6
Mutexes-Free: 2 and Full: 7
Buffer Writing: 7
Mutexes-Free: 1 and Full: 8
Buffer Writing: 8
Mutexes-Free: 0 and Full: 9
Buffer Writing: 9
Mutexes-Free: 0 and Full: 8
Buffer Writing: 10
Mutexes-Free: 2 and Full: 6
Buffer Writing: 11
Mutexes-Free: 1 and Full: 7
Buffer Writing: 12
Mutexes-Free: 0 and Full: 8
Buffer Writing: 13
Mutexes-Free: 0 and Full: 8
Buffer Writing: 14
Mutexes-Free: 0 and Full: 8
Buffer Writing: 15
Mutexes-Free: 0 and Full: 8
Buffer Writing: 16
Mutexes-Free: 1 and Full: 7
Buffer Writing: 17
Mutexes-Free: 0 and Full: 8
Buffer Writing: 18
Mutexes-Free: 0 and Full: 8
Buffer Writing: 19
Mutexes-Free: 0 and Full: 8
Buffer Writing: 20
Mutexes-Free: 0 and Full: 8
Buffer Writing: 21
Mutexes-Free: 0 and Full: 8
Buffer Writing: 22
Mutexes-Free: 0 and Full: 8
Buffer Writing: 23
Mutexes-Free: 0 and Full: 8
Buffer Writing: 24
Mutexes-Free: 0 and Full: 9
Buffer Writing: 0
ReadPointer: 0
WritePointer: 0
Mutexes-Free: 1 and Full: 8
Buffer Writing: 1
ReadPointer: 1
WritePointer: 0
Mutexes-Free: 1 and Full: 8
Buffer Writing: 2
ReadPointer: 2
WritePointer: 1
Mutexes-Free: 2 and Full: 7
Buffer Writing: 3
ReadPointer: 3
WritePointer: 1
Mutexes-Free: 2 and Full: 6
Buffer Writing: 4
ReadPointer: 4
WritePointer: 2
Mutexes-Free: 1 and Full: 7
Buffer Writing: 5
ReadPointer: 5
WritePointer: 4
Mutexes-Free: 1 and Full: 8
Buffer Writing: 6
ReadPointer: 6
WritePointer: 5
Mutexes-Free: 1 and Full: 8
Buffer Writing: 7
ReadPointer: 7
WritePointer: 7
Mutexes-Free: 1 and Full: 8
Buffer Writing: 8
ReadPointer: 8
WritePointer: 7
Mutexes-Free: 1 and Full: 7
Buffer Writing: 9
ReadPointer: 9
WritePointer: 8
Mutexes-Free: 1 and Full: 8
Buffer Writing: 10
ReadPointer: 0
WritePointer: 9
Mutexes-Free: 1 and Full: 7
Buffer Writing: 11
ReadPointer: 1
WritePointer: 0
Mutexes-Free: 1 and Full: 8
Buffer Writing: 12
ReadPointer: 2
WritePointer: 1
Mutexes-Free: 1 and Full: 7
Buffer Writing: 13
ReadPointer: 3
WritePointer: 2
Mutexes-Free: 1 and Full: 8
Buffer Writing: 14
ReadPointer: 4
WritePointer: 3
Mutexes-Free: 1 and Full: 8
Buffer Writing: 15
ReadPointer: 5
WritePointer: 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
最佳答案
您有许多小问题和指针的误用,但即使纠正了这些问题,您的作者/阅读者在复制文件时仍然会不一致 aaa.txt
至bbb.txt
.为什么?当您读取文件并写入共享内存并从中展开时,互斥逻辑会采用不同的路径。
我们先来看看需要多少小修正。除非您提供 typedef
, 你需要使用 struct MemData
作为带有 sizeof
的类型,或者更好地使用指针本身。接下来,strlen(M->Data)
无效,应为 sizeof (M->Data));
当与:
memset (M->Data, '\0', sizeof (M->Data));
&Buf
时遇到了指针问题。在:
memcpy(&M->Data[M->WritePointer*BufferSize], &Buf, sizeof(Buf)*sizeof(unsigned char));
Buf
已经是一个指针和
sizeof(unsigned char) == 1
.此外,如果您稍后分配
Buf
而不是使用 VLA
unsigned char Buf[BufferSize];
,
sizeof (Buf)
将是
sizeof (a_pointer)
.更好地使用:
memcpy (&M->Data[M->WritePointer*BufferSize], Buf, BufferSize);
FileSize
之后在 Writer.c 中与
StatBuf.st_size
,没有理由调用
ftell (FP)
因为您没有使用
fseek
移动文件位置指示器该代码中的任何位置。同样在 Writer.c 中,没有理由调用
fseek (FP, BufferCount*BufferSize, SEEK_SET);
因为您的阅读将随着每次阅读继续向前移动指示器。 (Reader.c 中的
fseek()
也有同样的问题)
Buf
是
Reader.c
中未使用的变量.
fread (Buf, 1, BufferSize, FP);
的返回。或
fwrite (&M->Data[M->ReadPointer * BufferSize], 1, BufferSize, FP);
.而在文件操作的情况下,您应该有
Buffersize
的竞争读取和写入。字节,不能保证,因此有必要检查返回(尤其是在读取具有奇数(51 字节)输入文件的 2 字节 block 时)。某处将读取或写入 1 个字节,如果您每次都盲目地写入 2 个字节,则某些事情将无法解决。
bbb.txt
的问题的症结所在。 (或写入比
aaa.txt
更多的字节)使用
M->FileEnding
作为指示输入结束的共享标志。这里有一个计数问题,我会让你解决。它从缓冲
10
开始(从文件中读取和)写入
Data
在你开始阅读之前。您的
Writer.c
计数器是
10
在
Reader.c
的柜台前之前
Reader.c
开始。这就是为什么在大多数运行中你有
16
Reader
的迭代次数当
Writer
设置
M->FileEnding
导致
Reader
写入
bbb.txt
的前 32 个字节并退出。 (然后在足够多的运行中,您实际上将写入
Buffer Writing: 22
次,或
Buffer Writing: 27
次,从而产生 58 字节的
bbb.txt
(所有数字都写入
1-20
,然后在最后写入一些杂散的
0
秒)。
M->FileEnding
标志被设置并被识别。花点时间回顾一下逻辑并确保您的
FullMutex
, 和
FreeMutex
逻辑正在做预期的事情。我的头顶上没有给你的 Elixir ,它需要逐个迭代地调试可以设置的可能组合——我把它留给你。
关于C Ring Buffer 共享内存信号量 ReadPointer WritePointer Not Right,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56266848/
我想使用 Reader-Writer Synchronization Paradigm 构建一个文件复制器。 Writer 初始化这两个互斥锁。 FullMutex 表示有多少 Buffer 可供写入
我是一名优秀的程序员,十分优秀!