Created
January 14, 2024 18:53
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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