#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <semaphore.h>
#include <time.h>
#include "SharedData.h"
static void cleanup(struct SharedData *sharedData, int shm_fd)
{
if (sharedData != NULL)
{
munmap(sharedData, sizeof(struct SharedData));
}
if (shm_fd != -1)
{
close(shm_fd);
}
sem_close(&sharedData->sem_empty);
sem_close(&sharedData->sem_full);
sem_close(&sharedData->sem_response);
}
int InitializeSharedData(struct SharedData **sharedData, char *shmName ,bool creatFlag)
{
int shm_fd = shm_open(shmName, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (shm_fd == -1)
{
perror("shm_open");
cleanup(NULL, shm_fd);
return 1;
}
if (ftruncate(shm_fd, sizeof(struct SharedData)) == -1)
{
perror("ftruncate");
cleanup(NULL, shm_fd);
return 2;
}
*sharedData = (struct SharedData *)mmap(NULL, sizeof(struct SharedData), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (*sharedData == MAP_FAILED)
{
perror("mmap");
cleanup(*sharedData, shm_fd);
return 3;
}
if (creatFlag)
{
memset(*sharedData, 0, sizeof(struct SharedData));
if (sem_init(&(*sharedData)->sem_empty, 1, BUFFER_SIZE) == -1 ||
sem_init(&(*sharedData)->sem_full, 1, 0) == -1 ||
sem_init(&(*sharedData)->sem_response, 1, 0) == -1)
{
perror("sem_init");
cleanup(*sharedData, shm_fd);
return 4;
}
}
else
{
int semValue;
sem_getvalue(&(*sharedData)->sem_empty, &semValue);
printf("action with sem_empty[%d]\n",semValue);
return 0;
}
return 0;
}
int ProducerEnqueue(struct SharedData *sharedData, const char *data)
{
struct timespec timeout;
memset(&timeout, 0, sizeof(timeout));
sem_wait(&sharedData->sem_empty);
memcpy(sharedData->buffer[sharedData->in], data, DATA_SIZE);
sharedData->in = (sharedData->in + 1) % BUFFER_SIZE;
sem_post(&sharedData->sem_full);
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 1;
if (sem_timedwait(&sharedData->sem_response, &timeout) == -1)
{
perror("sem_timedwait");
return -1;
}
}
void ConsumerDequeue(struct SharedData *sharedData, char *output)
{
int semValue = 0;
sem_wait(&sharedData->sem_full);
memcpy(output, sharedData->buffer[sharedData->out], DATA_SIZE);
memcpy(sharedData->response, sharedData->buffer[sharedData->out], DATA_SIZE);
sharedData->out = (sharedData->out + 1) % BUFFER_SIZE;
sem_post(&sharedData->sem_empty);
sem_getvalue(&sharedData->sem_response, &semValue);
if (!semValue)
{
sem_post(&sharedData->sem_response);
}
}
#ifndef SHARED_DATA_H
#define SHARED_DATA_H
#include <semaphore.h>
#include <stdbool.h>
#define DATA_SIZE 256
#define BUFFER_SIZE 5
#pragma pack(1)
struct SharedData
{
char buffer[BUFFER_SIZE][DATA_SIZE];
int in;
int out;
char response[DATA_SIZE];
sem_t sem_empty;
sem_t sem_full;
sem_t sem_response;
};
#pragma pack()
int InitializeSharedData(struct SharedData **sharedData, char *shmName ,bool creatFlag);
int ProducerEnqueue(struct SharedData *sharedData, const char *data);
void ConsumerDequeue(struct SharedData *sharedData, char *output);
#endif
#include <stdio.h>
#include <semaphore.h>
#include "SharedData.h"
#define SHM_NAME "/my_shared_memory"
int main()
{
struct SharedData *sharedData = NULL;
int ret = 0;
if (InitializeSharedData(&sharedData, SHM_NAME, true) != 0)
{
return 1;
}
while (1)
{
char input[DATA_SIZE];
memset(input, 0, sizeof(input));
printf("请输入生产者要生成的数据: ");
if (fgets(input, DATA_SIZE, stdin) != NULL)
{
input[strcspn(input, "\n")] = '\0';
}
ret = ProducerEnqueue(sharedData, input);
if (ret)
{
printf("ConsumerDequeue: 超时,没有收到数据\n");
}
printf("生产者收到回应: [%s]\n", sharedData->response);
}
return 0;
}
#include <stdio.h>
#include <semaphore.h>
#include "SharedData.h"
#define SHM_NAME "/my_shared_memory"
int main()
{
struct SharedData *sharedData = NULL;
char output[DATA_SIZE];
if (InitializeSharedData(&sharedData, SHM_NAME, false) != 0)
{
return 1;
}
while (1)
{
memset(output, 0, sizeof(output));
ConsumerDequeue(sharedData, output);
printf("消费者读取: [%s]\n", output);
}
return 0;
}
- 因为将无名信号量也放进共享内存中了,所以可使用其进行进程间同步
- 需要先启动生产者进程