在嵌入式开发中经常会涉及资源抢占的问题,一般会有这些情景:
- 1、输入和输出不一致
- 2、一写多读
缓冲区还多用在网络收发中,经常会因为网络抖动,为了保证读取的稳定,收到的数据会先写入缓冲区,之后在缓冲区中读取数据,这样可以一定程度的抵抗网络抖动。当然,缓冲区的大小也是有限的,当缓冲区没有数据的时候,就没什么作用了。
下面是我用过的几种缓冲区设计:
1、针对固定块大小,使用二维数组来实现
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include "stdint.h"
#include "pthread.h"
#include "string.h"
#include "stdbool.h"
// #include "tphub_ringbuf.h"
#define DATA_SIZE 960
#define READ_SIZE 480
typedef struct {
signed char **buffer; // 二维数组
size_t bufferSize; // 缓冲区大小
size_t writePos; // 写入位置
size_t readPos; // 读取位置
pthread_mutex_t mutex;
pthread_cond_t cond;
bool dataAvailable; // 表示缓冲区中是否有可读数据
size_t dataSize; // 每次拷贝的大小
int firstRead;
} RingBuffer;
#define blockSize 2
bool stopReading = false;
/*
bufferSize :是块的数量
dataSize:每个块的大小
*/
int RingBuffer_Init(RingBuffer *ringBuffer, size_t bufferSize, size_t dataSize)
{
if(ringBuffer == NULL)
{
return -1;
}
ringBuffer->buffer = (signed char**)malloc(bufferSize * sizeof(signed char*));
if(ringBuffer->buffer == NULL)
{
return -1;
}
for (size_t i = 0; i < bufferSize; ++i) {
ringBuffer->buffer[i] = (signed char*)malloc(dataSize);
if (ringBuffer->buffer[i] == NULL)
{
for(size_t j = 0; j<i; j++)
{
free(ringBuffer->buffer[j]);
}
free(ringBuffer->buffer);
return -1;
}
}
ringBuffer->bufferSize = bufferSize;
ringBuffer->dataSize = dataSize;
ringBuffer->writePos = 0;
ringBuffer->readPos = 0;
ringBuffer->dataAvailable = false;
ringBuffer->firstRead = 0;
pthread_mutex_init(&ringBuffer->mutex, NULL);
pthread_cond_init(&ringBuffer->cond, NULL);
return 0;
}
bool RingBuffer_Write(RingBuffer *ringBuffer, const void *data, size_t dataSize)
{
if(ringBuffer == NULL)
{
return -1;
}
pthread_mutex_lock(&ringBuffer->mutex);
if ((ringBuffer->writePos + dataSize) % ringBuffer->bufferSize == ringBuffer->readPos)
{
pthread_mutex_unlock(&ringBuffer->mutex);
return false; // 缓冲区已满,写入失败
}
for (size_t i = 0; i < dataSize; ++i)
{
memcpy(ringBuffer->buffer[ringBuffer->writePos], (char *)data + i * ringBuffer->dataSize, ringBuffer->dataSize);
ringBuffer->writePos = (ringBuffer->writePos + 1) % ringBuffer->bufferSize;
}
ringBuffer->dataAvailable = true;
pthread_cond_signal(&ringBuffer->cond);
pthread_mutex_unlock(&ringBuffer->mutex);
return true;
}
/*修改了读的代码*/
size_t RingBuffer_Read(RingBuffer *ringBuffer, void *outData, size_t maxSize)
{
if(ringBuffer == NULL)
{
return -1;
}
pthread_mutex_lock(&ringBuffer->mutex);
if (!ringBuffer->firstRead) {
while (!ringBuffer->dataAvailable || (ringBuffer->writePos - ringBuffer->readPos) < blockSize)
{
pthread_cond_wait(&ringBuffer->cond, &ringBuffer->mutex);
}
ringBuffer->firstRead = true;
}
else
{
while (!ringBuffer->dataAvailable)
{
pthread_cond_wait(&ringBuffer->cond, &ringBuffer->mutex);
}
}
size_t i;
for (i = 0; i < maxSize && ringBuffer->readPos != ringBuffer->writePos; ++i)
{
memcpy((char *)outData + i * ringBuffer->dataSize, ringBuffer->buffer[ringBuffer->readPos], ringBuffer->dataSize);
ringBuffer->readPos = (ringBuffer->readPos + 1) % ringBuffer->bufferSize;
}
if (ringBuffer->readPos == ringBuffer->writePos)
{
ringBuffer->dataAvailable = false;
}
pthread_mutex_unlock(&ringBuffer->mutex);
return i; // 返回实际读取的数据大小
}
int RingBuffer_Destroy(RingBuffer *ringBuffer)
{
if(ringBuffer == NULL)
{
return -1;
}
for (size_t i = 0; i < ringBuffer->bufferSize; ++i)
{
if(ringBuffer->buffer[i] != NULL)
{
free(ringBuffer->buffer[i]);
}
else
{
return -1;
}
}
free(ringBuffer->buffer);
pthread_mutex_destroy(&ringBuffer->mutex);
pthread_cond_destroy(&ringBuffer->cond);
return 0;
}
RingBuffer ringBuffer;
void *writeThread(void *arg) {
FILE *pcmFile = fopen("audio.pcm", "rb");
if (pcmFile == NULL) {
perror("Error opening input.pcm file");
return NULL;
}
char data[DATA_SIZE];
while (fread(data, sizeof(char), DATA_SIZE, pcmFile) == DATA_SIZE) {
RingBuffer_Write(&ringBuffer, data, 2);
usleep(128000); // 128ms
}
stopReading = true;
fclose(pcmFile);
return NULL;
}
void *readThread(void *arg) {
FILE *pcmFile = fopen("output.pcm", "wb");
if (pcmFile == NULL) {
perror("Error opening output.pcm file");
return NULL;
}
char outData[READ_SIZE];
while (!stopReading) {
RingBuffer_Read(&ringBuffer, outData, 1);
fwrite(outData, sizeof(char), READ_SIZE, pcmFile);
usleep(64000); // 64ms
}
fclose(pcmFile);
return NULL;
}
int main() {
RingBuffer_Init(&ringBuffer, 10, READ_SIZE);
pthread_t writeTid, readTid;
pthread_create(&writeTid, NULL, writeThread, NULL);
pthread_create(&readTid, NULL, readThread, NULL);
pthread_join(writeTid, NULL);
pthread_join(readTid, NULL);
RingBuffer_Destroy(&ringBuffer);
return 0;
}
运行后结果如下:
2、使用共享内存实现缓冲区
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <pthread.h>
#define SHM_NAME "my_shared_memory"
#define SHM_SIZE 5000 // 假设足以存储10个spk帧
#define SPK_FRAME_SIZE 500
#define MIC_FRAME_SIZE 256
// 环形缓冲区结构
typedef struct
{
char buffer[SHM_SIZE];
int write_pos;
int read_pos;
pthread_mutex_t mutex;
pthread_cond_t cond;
} ring_buffer_t;
// 初始化环形缓冲区
void init_buffer(ring_buffer_t *rb)
{
pthread_mutex_init(&rb->mutex, NULL);
pthread_cond_init(&rb->cond, NULL);
rb->write_pos = 0;
rb->read_pos = 0;
}
// 写入缓冲区的函数
void write_to_buffer(ring_buffer_t *rb, const char *data, int size)
{
pthread_mutex_lock(&rb->mutex);
while ((rb->write_pos - rb->read_pos + SHM_SIZE) % SHM_SIZE >= SHM_SIZE - size)
{
// 缓冲区已满,覆盖旧数据
rb->read_pos = (rb->read_pos + size) % SHM_SIZE;
printf("Buffer is full, overwriting old data\n");
}
memcpy(rb->buffer + rb->write_pos, data, size);
rb->write_pos = (rb->write_pos + size) % SHM_SIZE;
pthread_cond_signal(&rb->cond);
pthread_mutex_unlock(&rb->mutex);
}
// 从缓冲区读取数据的函数
void read_from_buffer(ring_buffer_t *rb, char *data, int size)
{
pthread_mutex_lock(&rb->mutex);
while ((rb->write_pos - rb->read_pos + SHM_SIZE) % SHM_SIZE < size)
{
printf("Buffer is empty, waiting for data\n");
pthread_cond_wait(&rb->cond, &rb->mutex);
}
memcpy(data, rb->buffer + rb->read_pos, size);
rb->read_pos = (rb->read_pos + size) % SHM_SIZE;
pthread_mutex_unlock(&rb->mutex);
}
void *spk_thread(void *arg)
{
usleep(1000000);
ring_buffer_t *rb = (ring_buffer_t *)arg;
char spk_data[SPK_FRAME_SIZE];
while (1)
{
// 生成模拟的spk数据
for (int i = 0; i < SPK_FRAME_SIZE; ++i)
{
spk_data[i] = rand() % 256;
}
write_to_buffer(rb, spk_data, SPK_FRAME_SIZE);
printf("SPK: Wrote data to buffer\n");
usleep(1000000); // 10ms
}
return NULL;
}
void *mic_thread(void *arg)
{
ring_buffer_t *rb = (ring_buffer_t *)arg;
char mic_data[MIC_FRAME_SIZE];
while (1)
{
read_from_buffer(rb, mic_data, MIC_FRAME_SIZE);
printf("MIC: Read data from buffer\n");
usleep(500000); // 5ms
}
return NULL;
}
int main()
{
int shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, sizeof(ring_buffer_t));
ring_buffer_t *rb = (ring_buffer_t *)mmap(0, sizeof(ring_buffer_t), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
init_buffer(rb);
pthread_t spk_tid, mic_tid;
pthread_create(&spk_tid, NULL, spk_thread, rb);
pthread_create(&mic_tid, NULL, mic_thread, rb);
printf("Main: Started SPK and MIC threads\n");
pthread_join(spk_tid, NULL);
pthread_join(mic_tid, NULL);
pthread_mutex_destroy(&rb->mutex);
pthread_cond_destroy(&rb->cond);
munmap(rb, sizeof(ring_buffer_t));
close(shm_fd);
shm_unlink(SHM_NAME);
printf("Main: Exiting program\n");
return 0;
}
运行结果如下:
3、通过读写文件实现一个缓冲区
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#define FILE_NAME "queue_file"
#define FILE_SIZE 24
#define WRITE_SIZE 12
#define READ_SIZE 3
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 写入数据到队列文件
void write_to_queue_file(const char *data, int size, int *write_position) {
pthread_mutex_lock(&mutex);
FILE *file = fopen(FILE_NAME, "r+");
if (file == NULL) {
perror("Error opening file");
exit(1);
}
// 将文件指针移动到当前写入位置
fseek(file, *write_position, SEEK_SET);
// 写入数据
fwrite(data, 1, size, file);
*write_position = (*write_position + size) % FILE_SIZE; // 更新写入位置
fclose(file);
pthread_mutex_unlock(&mutex);
}
// 从队列文件读取数据
void read_from_queue_file(char *data, int size, int *read_position) {
pthread_mutex_lock(&mutex);
FILE *file = fopen(FILE_NAME, "r");
if (file == NULL) {
perror("Error opening file");
exit(1);
}
// 将文件指针移动到当前读取位置
fseek(file, *read_position, SEEK_SET);
// 读取数据
fread(data, 1, size, file);
*read_position = (*read_position + size) % FILE_SIZE; // 更新读取位置
fclose(file);
pthread_mutex_unlock(&mutex);
}
// 线程函数:写入数据到队列文件
void *write_thread_function(void *arg) {
const char *data1 = "111222333444";
int write_position = 0;
while (1) {
write_to_queue_file(data1, WRITE_SIZE, &write_position);
usleep(1000000);
}
}
// 线程函数:从队列文件读取数据
void *read_thread_function(void *arg) {
char read_data[READ_SIZE] = "123";
int read_position = 0;
while (1) {
read_from_queue_file(read_data, READ_SIZE, &read_position);
printf("Read from queue file: %s\n", read_data);
usleep(190000);
}
}
int main() {
// 创建固定大小的空洞文件
FILE *file = fopen(FILE_NAME, "w");
fseek(file, FILE_SIZE - 1, SEEK_SET);
fputc('\0', file);
fclose(file);
// 创建写入线程和读取线程
pthread_t write_thread, read_thread;
pthread_create(&write_thread, NULL, write_thread_function, NULL);
pthread_create(&read_thread, NULL, read_thread_function, NULL);
// 主线程等待线程结束
pthread_join(write_thread, NULL);
pthread_join(read_thread, NULL);
return 0;
}
4、支持一写多读的缓冲区
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#define BUFFER_SIZE 4096 // 环形缓冲区大小
typedef struct
{
unsigned char *buffer; // 缓冲区
size_t bufferSize;
size_t writePos;
size_t *readPos; // 动态分配读取位置数组
size_t numReaders; // 读取者数量
pthread_mutex_t mutex;
pthread_cond_t cond;
bool isWritingDone;
} RingBuffer;
typedef struct
{
RingBuffer *ringBuffer;
size_t readSize;
int readerIndex;
unsigned int waitTimeUs;
char outputFilename[256];
} ReaderArgs;
void RingBuffer_Init(RingBuffer *ringBuffer, size_t numReaders)
{
ringBuffer->buffer = (unsigned char *)malloc(BUFFER_SIZE);
ringBuffer->bufferSize = BUFFER_SIZE;
ringBuffer->writePos = 0;
ringBuffer->readPos = (size_t *)malloc(numReaders * sizeof(size_t));
memset(ringBuffer->readPos, 0, numReaders * sizeof(size_t));
ringBuffer->numReaders = numReaders;
pthread_mutex_init(&ringBuffer->mutex, NULL);
pthread_cond_init(&ringBuffer->cond, NULL);
ringBuffer->isWritingDone = false;
}
bool RingBuffer_Write(RingBuffer *ringBuffer, const unsigned char *data, size_t dataSize)
{
pthread_mutex_lock(&ringBuffer->mutex);
size_t endPos = (ringBuffer->writePos + dataSize) % ringBuffer->bufferSize;
if (dataSize <= ringBuffer->bufferSize - ringBuffer->writePos)
{
memcpy(ringBuffer->buffer + ringBuffer->writePos, data, dataSize);
}
else
{
size_t firstChunk = ringBuffer->bufferSize - ringBuffer->writePos;
memcpy(ringBuffer->buffer + ringBuffer->writePos, data, firstChunk);
memcpy(ringBuffer->buffer, data + firstChunk, dataSize - firstChunk);
}
ringBuffer->writePos = endPos;
pthread_cond_broadcast(&ringBuffer->cond);
pthread_mutex_unlock(&ringBuffer->mutex);
return true;
}
size_t RingBuffer_Read(RingBuffer *ringBuffer, unsigned char *outData, size_t maxSize, int readerIndex)
{
pthread_mutex_lock(&ringBuffer->mutex);
while (ringBuffer->readPos[readerIndex] == ringBuffer->writePos && !ringBuffer->isWritingDone)
{
pthread_cond_wait(&ringBuffer->cond, &ringBuffer->mutex);
}
if (ringBuffer->isWritingDone && ringBuffer->readPos[readerIndex] == ringBuffer->writePos)
{
pthread_mutex_unlock(&ringBuffer->mutex);
return 0; // No more data to read.
}
size_t availableBytes = (ringBuffer->writePos + ringBuffer->bufferSize - ringBuffer->readPos[readerIndex]) % ringBuffer->bufferSize;
size_t bytesToRead = (maxSize < availableBytes) ? maxSize : availableBytes;
if (bytesToRead <= ringBuffer->bufferSize - ringBuffer->readPos[readerIndex])
{
memcpy(outData, ringBuffer->buffer + ringBuffer->readPos[readerIndex], bytesToRead);
}
else
{
size_t firstChunk = ringBuffer->bufferSize - ringBuffer->readPos[readerIndex];
memcpy(outData, ringBuffer->buffer + ringBuffer->readPos[readerIndex], firstChunk);
memcpy(outData + firstChunk, ringBuffer->buffer, bytesToRead - firstChunk);
}
ringBuffer->readPos[readerIndex] = (ringBuffer->readPos[readerIndex] + bytesToRead) % ringBuffer->bufferSize;
pthread_mutex_unlock(&ringBuffer->mutex);
return bytesToRead;
}
void RingBuffer_Destroy(RingBuffer *ringBuffer)
{
if (ringBuffer->buffer != NULL)
{
free(ringBuffer->buffer);
}
pthread_mutex_destroy(&ringBuffer->mutex);
pthread_cond_destroy(&ringBuffer->cond);
}
void *writer_thread(void *arg)
{
RingBuffer *ringBuffer = (RingBuffer *)arg;
FILE *file = fopen("audio.pcm", "rb");
if (!file)
{
printf("Unable to open PCM file for reading.\n");
return NULL;
}
unsigned char data[960];
while (fread(data, 1, sizeof(data), file) == sizeof(data))
{
RingBuffer_Write(ringBuffer, data, sizeof(data));
usleep(128000); // wait for 128ms
}
fclose(file);
ringBuffer->isWritingDone = true;
pthread_cond_broadcast(&ringBuffer->cond); // Notify all waiting readers
return NULL;
}
void *reader_thread(void *arg)
{
ReaderArgs *rargs = (ReaderArgs *)arg;
FILE *outputFile = fopen(rargs->outputFilename, "wb");
if (!outputFile)
{
printf("Unable to open PCM file for writing: %s\n", rargs->outputFilename);
return NULL;
}
unsigned char *data = (unsigned char *)malloc(rargs->readSize);
size_t bytesRead;
while ((bytesRead = RingBuffer_Read(rargs->ringBuffer, data, rargs->readSize, rargs->readerIndex)) > 0 || !rargs->ringBuffer->isWritingDone)
{
fwrite(data, 1, bytesRead, outputFile);
usleep(rargs->waitTimeUs); // wait for specified time
}
free(data);
fclose(outputFile);
return NULL;
}
int main()
{
RingBuffer ringBuffer;
size_t numReaders = 2;
RingBuffer_Init(&ringBuffer, numReaders);
pthread_t writer;
pthread_create(&writer, NULL, writer_thread, &ringBuffer);
ReaderArgs rargs1 = {&ringBuffer, 480, 0, 64000, "output1.pcm"};
ReaderArgs rargs2 = {&ringBuffer, 128, 1, 10000, "output2.pcm"};
pthread_t reader1, reader2;
pthread_create(&reader1, NULL, reader_thread, &rargs1);
pthread_create(&reader2, NULL, reader_thread, &rargs2);
pthread_join(writer, NULL);
pthread_join(reader1, NULL);
pthread_join(reader2, NULL);
RingBuffer_Destroy(&ringBuffer);
return 0;
}
这个缓冲区支持一写多读,测试程序创建了两个读线程一个写线程,读线程读取一个pcm文件,每隔128ms写入缓冲区,每次写入960个字节的数据,读线程有两个,一个每次读取480个字节的数据,读取间隔为64ms,一个每次读取128字节的数据,读取间隔为10ms。最终读取效果如下所示:
5、另一种支持一读多写的缓冲区
test.c
#include "ringbuf.h"
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
circular_buffer cb_global;
void *writer_thread(void *arg)
{
circular_buffer *cb = (circular_buffer *)arg;
char input_data[1024] = {0};
while (1)
{
if (cb_write(cb, input_data, 1024) == 1024)
{
printf("write over \n");
}
else
{
printf("write error \n");
}
sleep(1);
}
return NULL;
}
void *reader_thread1(void *arg)
{
int reader_id = *(int *)arg;
circular_buffer *cb = &cb_global;
char data[512];
while (1)
{
int bytes_read = cb_read(cb, data, sizeof(data), reader_id, 960);
if (bytes_read > 0)
{
printf("Reader %d read %d\n", reader_id, bytes_read);
}
sleep(0.5);
}
return NULL;
}
void *reader_thread2(void *arg)
{
int reader_id = *(int *)arg;
circular_buffer *cb = &cb_global;
char data[256];
while (1)
{
int bytes_read = cb_read(cb, data, sizeof(data), reader_id, 256);
if (bytes_read > 0)
{
printf("Reader %d read %d\n", reader_id, bytes_read);
}
sleep(0.25);
}
return NULL;
}
int main()
{
cb_init(&cb_global, 4096);
pthread_t writer, reader1, reader2;
int reader1_id = cb_register_reader(&cb_global, 512);
int reader2_id = cb_register_reader(&cb_global, 256);
pthread_create(&writer, NULL, writer_thread, (void *)&cb_global);
pthread_create(&reader1, NULL, reader_thread1, (void *)&reader1_id);
pthread_create(&reader2, NULL, reader_thread2, (void *)&reader2_id);
pthread_join(writer, NULL);
pthread_join(reader1, NULL);
pthread_join(reader2, NULL);
cb_free(&cb_global);
return 0;
}
ringbuf.c
#include "ringbuf.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int cb_init(circular_buffer *cb, int size)
{
cb->size = size;
cb->buffer = (char *)malloc(size);
if (!cb->buffer)
return -1;
cb->write_pos = 0;
cb->reader_count = 0;
memset(cb->read_pos, 0, sizeof(cb->read_pos));
memset(cb->read_size, 0, sizeof(cb->read_size));
pthread_mutex_init(&cb->mutex, NULL);
pthread_cond_init(&cb->can_write, NULL);
for (int i = 0; i < MAX_READERS; i++)
{
cb->can_read[i] = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
}
return 0;
}
void cb_free(circular_buffer *cb)
{
free(cb->buffer);
pthread_mutex_destroy(&cb->mutex);
pthread_cond_destroy(&cb->can_write);
for (int i = 0; i < MAX_READERS; i++)
{
pthread_cond_destroy(&cb->can_read[i]);
}
}
int cb_write(circular_buffer *cb, const char *data, int size)
{
pthread_mutex_lock(&cb->mutex);
int written = 0;
while (written < size)
{
int next_pos = (cb->write_pos + 1) % cb->size;
int can_write = 1;
for (int i = 0; i < cb->reader_count; i++)
{
if (next_pos == cb->read_pos[i])
{
can_write = 0;
break;
}
}
if (can_write)
{
cb->buffer[cb->write_pos] = data[written++];
cb->write_pos = next_pos;
}
else
{
pthread_cond_wait(&cb->can_write, &cb->mutex);
}
}
for (int i = 0; i < cb->reader_count; i++)
{
pthread_cond_signal(&cb->can_read[i]);
}
pthread_mutex_unlock(&cb->mutex);
return written;
}
int cb_read(circular_buffer *cb, char *data, int size, int reader_id, int blocking)
{
pthread_mutex_lock(&cb->mutex);
int read = 0;
while (read < size)
{
int can_read = (cb->write_pos + cb->size - cb->read_pos[reader_id]) % cb->size >= cb->read_size[reader_id];
if (can_read)
{
data[read++] = cb->buffer[cb->read_pos[reader_id]];
cb->read_pos[reader_id] = (cb->read_pos[reader_id] + 1) % cb->size;
}
else if (blocking)
{
pthread_cond_wait(&cb->can_read[reader_id], &cb->mutex);
}
else
{
break;
}
}
if (read > 0)
{
pthread_cond_signal(&cb->can_write);
}
pthread_mutex_unlock(&cb->mutex);
return read;
}
int cb_register_reader(circular_buffer *cb, int read_size)
{
pthread_mutex_lock(&cb->mutex);
int reader_id = cb->reader_count;
if (reader_id < MAX_READERS)
{
cb->read_size[reader_id] = read_size;
cb->read_pos[reader_id] = cb->write_pos;
cb->reader_count++;
}
else
{
reader_id = -1;
}
pthread_mutex_unlock(&cb->mutex);
return reader_id;
}
ringbuf.h
#ifndef RINGBUF_H
#define RINGBUF_H
#include <pthread.h>
#define MAX_READERS 3 // 最大读线程数
typedef struct
{
char *buffer;
int size;
int write_pos;
int read_pos[MAX_READERS];
int read_size[MAX_READERS];
int reader_count;
pthread_mutex_t mutex;
pthread_cond_t can_write;
pthread_cond_t can_read[MAX_READERS];
} circular_buffer;
int cb_init(circular_buffer *cb, int size);
void cb_free(circular_buffer *cb);
int cb_write(circular_buffer *cb, const char *data, int size);
int cb_read(circular_buffer *cb, char *data, int size, int reader_id, int blocking);
int cb_register_reader(circular_buffer *cb, int read_size);
#endif // RINGBUF_H
最终效果如下所示:
总结来看,支持一读多写的缓冲区其实就是设计了两个读的游标,然后写的部分写完后广播给其他进程来读取数据。