Skip to content

Instantly share code, notes, and snippets.

@JustSlavic
Created January 14, 2024 18:53
Show Gist options
  • Save JustSlavic/b0e40c3444b141f5834a1228b39b5432 to your computer and use it in GitHub Desktop.
Save JustSlavic/b0e40c3444b141f5834a1228b39b5432 to your computer and use it in GitHub Desktop.
Example of using shared memory for interprocess communication (a dialogue between Alice and Bob)
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/types.h>
char *chat_messages[] = {
"Hello, Bob! How are you?",
"Ah, Jessica is feeling better, she really is strong creature.",
"Yeah, I really wanna give Jessica a friend to play with. Your dog is ok too?",
"Did you meet with him?",
"I'm sorry, I gotta go now, let's meet by my place and play some videogames together?",
"Tomorrow then, bye!",
};
#define ARRAY_COUNT(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
#define SHARED_MEMORY_OBJECT_PATH "/tmp/alice_bob_comms_1"
#define SERVER_SEMAPHORE_NAME "/sem_alice"
#define CLIENT_SEMAPHORE_NAME "/sem_bob"
#define CHANNEL_SIZE 1024
struct shared_memory_channel
{
unsigned int bytes_available;
char message[CHANNEL_SIZE];
};
typedef struct shared_memory_channel shared_memory_channel;
int main()
{
shared_memory_channel *channel = NULL;
int shm_fd = shm_open(SHARED_MEMORY_OBJECT_PATH, O_CREAT | O_EXCL | O_RDWR, 0600);
if (shm_fd < 0)
{
printf("Could not open shared memory object (errno: %d - \"%s\")\n", errno, strerror(errno));
if (errno == EEXIST)
{
shm_unlink(SHARED_MEMORY_OBJECT_PATH);
}
}
else
{
int trunc_result = ftruncate(shm_fd, sizeof(shared_memory_channel));
if (trunc_result < 0)
{
printf("Could not truncate(%d, %lu) shared memory object (errno: %d - \"%s\")\n", shm_fd, sizeof(shared_memory_channel), errno, strerror(errno));
}
else
{
channel = mmap(NULL, sizeof(shared_memory_channel), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (channel == MAP_FAILED)
{
printf("Could not map shared memory object %d (errno: %d - \"%s\")\n", shm_fd, errno, strerror(errno));
}
else
{
sem_t *server_wait = sem_open(SERVER_SEMAPHORE_NAME, O_CREAT | O_EXCL, 0600, 0);
if (server_wait == SEM_FAILED)
{
printf("Could not open server semaphore \"%s\" (errno: %d - \"%s\")\n", SERVER_SEMAPHORE_NAME, errno, strerror(errno));
if (errno == EEXIST)
{
sem_unlink(SERVER_SEMAPHORE_NAME);
}
}
else
{
sem_t *client_wait = sem_open(CLIENT_SEMAPHORE_NAME, O_CREAT | O_EXCL, 0600, 1);
if (client_wait == SEM_FAILED)
{
printf("Could not open client semaphore \"%s\" (errno: %d - \"%s\")\n", CLIENT_SEMAPHORE_NAME, errno, strerror(errno));
if (errno == EEXIST)
{
sem_unlink(CLIENT_SEMAPHORE_NAME);
}
}
else
{
int running = 1;
while (running)
{
int wait_result = sem_trywait(server_wait);
if (wait_result < 0)
{
if (errno == EAGAIN)
{
sleep(1);
}
else
{
printf("Waiting on semaphore is failed (errno: %d - \"%s\")\n", errno, strerror(errno));
running = 0;
}
}
else
{
static int message_counter = 0;
printf("Bob: %.*s\n", (int) channel->bytes_available, channel->message);
printf("Alice: %s\n\n", chat_messages[message_counter]);
int len = strlen(chat_messages[message_counter]);
memcpy(channel->message, chat_messages[message_counter], len);
channel->bytes_available = len;
sem_post(client_wait);
message_counter++;
if (message_counter >= ARRAY_COUNT(chat_messages))
{
break;
}
}
}
sem_close(client_wait);
sem_unlink(CLIENT_SEMAPHORE_NAME);
}
sem_close(server_wait);
sem_unlink(SERVER_SEMAPHORE_NAME);
}
}
}
shm_unlink(SHARED_MEMORY_OBJECT_PATH);
}
return 0;
}
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/types.h>
char *chat_messages[] = {
"Hello, Alice!",
"I'm good, thanks! How's your cat?",
"I heard you plan on getting abother cat, is that true?",
"Max is ok, I guess. He really misses my ex.",
"Nah, I thought he would wanna visit Max, but he's such a douchbag...",
"Sounds like a good idea!",
"Have a good day! Bye!",
};
#define ARRAY_COUNT(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
#define SHARED_MEMORY_OBJECT_PATH "/tmp/alice_bob_comms_1"
#define SERVER_SEMAPHORE_NAME "/sem_alice"
#define CLIENT_SEMAPHORE_NAME "/sem_bob"
#define CHANNEL_SIZE 1024
struct shared_memory_channel
{
unsigned int bytes_available;
char message[CHANNEL_SIZE];
};
typedef struct shared_memory_channel shared_memory_channel;
int main()
{
shared_memory_channel *channel = NULL;
int shm_fd = shm_open(SHARED_MEMORY_OBJECT_PATH, O_CREAT | O_RDWR, 0600);
if (shm_fd < 0)
{
printf("Could not open shared memory object (errno: %d - \"%s\")\n", errno, strerror(errno));
}
else
{
channel = mmap(NULL, sizeof(shared_memory_channel), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (channel == MAP_FAILED)
{
printf("Could not map shared memory object\n");
}
else
{
sem_t *server_wait = sem_open(SERVER_SEMAPHORE_NAME, 0);
if (server_wait == SEM_FAILED)
{
printf("Could not open server semaphore \"%s\" (errno: %d - \"%s\")\n", SERVER_SEMAPHORE_NAME, errno, strerror(errno));
}
else
{
sem_t *client_wait = sem_open(CLIENT_SEMAPHORE_NAME, 0);
if (client_wait == SEM_FAILED)
{
printf("Could not open client semaphore \"%s\" (errno: %d - \"%s\")\n", CLIENT_SEMAPHORE_NAME, errno, strerror(errno));
}
else
{
int running = 1;
while (running)
{
int try_wait_result = sem_trywait(client_wait);
if (try_wait_result < 0)
{
if (errno == EAGAIN)
{
sleep(1);
}
else
{
printf("Waiting on semaphore is failed (errno: %d - \"%s\")\n", errno, strerror(errno));
running = 0;
}
}
else
{
static int message_counter = 0;
if (message_counter > 0)
printf("Alice: %.*s\n", (int) channel->bytes_available, channel->message);
printf("Bob: %s\n\n", chat_messages[message_counter]);
int len = strlen(chat_messages[message_counter]);
memcpy(channel->message, chat_messages[message_counter], len);
channel->bytes_available = len;
sem_post(server_wait);
message_counter += 1;
if (message_counter >= ARRAY_COUNT(chat_messages))
{
break;
}
}
}
sem_close(client_wait);
}
sem_close(server_wait);
}
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment