diff --git a/test/apps/Makefile b/test/apps/Makefile index a04c577bc..1bfc85a01 100644 --- a/test/apps/Makefile +++ b/test/apps/Makefile @@ -34,6 +34,7 @@ TEST_APPS := \ pipe \ pthread \ pty \ + shm \ signal_c \ vsock \ diff --git a/test/apps/scripts/process.sh b/test/apps/scripts/process.sh index 68845b9e9..ae263abe0 100755 --- a/test/apps/scripts/process.sh +++ b/test/apps/scripts/process.sh @@ -30,6 +30,7 @@ mmap/mmap_shared_filebacked mmap/mmap_readahead pthread/pthread_test pty/open_pty +shm/posix_shm signal_c/parent_death_signal signal_c/signal_test " diff --git a/test/apps/shm/Makefile b/test/apps/shm/Makefile new file mode 100644 index 000000000..c603a781a --- /dev/null +++ b/test/apps/shm/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MPL-2.0 + +include ../test_common.mk + +EXTRA_C_FLAGS := diff --git a/test/apps/shm/posix_shm.c b/test/apps/shm/posix_shm.c new file mode 100644 index 000000000..bd44a5df8 --- /dev/null +++ b/test/apps/shm/posix_shm.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: MPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +// ============================================================================ +// Helper macros +// ============================================================================ + +#define SHM_OBJ "shm_test" // Name of shared memory object +#define SHM_SIZE 0x1000 // Size (in bytes) of shared memory object + +#define THROW_ERROR(msg) \ + do { \ + perror(msg); \ + exit(EXIT_FAILURE); \ + } while (0) + +/* Messages to communicate through shared memory */ +#define MSG0 "1st Hello" +#define MSG1 "2nd Hello" +#define MSG2 "3rd Hello" +#define MSG3 "4th Hello" +#define MSG_SIZE (strlen(MSG0) + 1) + +// ============================================================================ +// Test functions for producer and consumer to communicate through shared memory +// ============================================================================ + +int producer_process() +{ + // Shared memory file descriptor + int shm_fd; + // Shared memory buffer + void *shm_buf; + + // Create the shared memory object + shm_fd = shm_open(SHM_OBJ, O_CREAT | O_RDWR, 0666); + if (shm_fd < 0) { + THROW_ERROR("shm_open failed"); + } + + // Configure the size of the shared memory object + if (ftruncate(shm_fd, SHM_SIZE) < 0) { + THROW_ERROR("ftruncate error"); + } + + // Memory map the shared memory object + shm_buf = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, 0); + if (shm_buf == MAP_FAILED) { + THROW_ERROR("mmap(MAP_SHARED) failed"); + } + + // Fork a child and launch consumer process + pid_t child_pid = fork(); + if (child_pid < 0) { + THROW_ERROR("Spawn a child process failed"); + } else if (child_pid == 0) { + execl("/test/shm/posix_shm", "posix_shm", "consumer", NULL); + THROW_ERROR("exec failed"); + } + + // Communicate through shared memory + strncpy(shm_buf, MSG0, MSG_SIZE); + printf("[Producer] send %s\n", MSG0); + while (1) { + if (strncmp(shm_buf, MSG1, MSG_SIZE) != 0) { + sleep(1); + continue; + } + printf("[Producer] receive %s\n", MSG1); + strncpy(shm_buf, MSG2, MSG_SIZE); + printf("[Producer] send %s\n", MSG2); + while (1) { + if (strncmp(shm_buf, MSG3, MSG_SIZE) != 0) { + sleep(1); + continue; + } + printf("[Producer] receive %s\n", MSG3); + break; + } + break; + } + + // Unmap the shared memory + if (munmap(shm_buf, SHM_SIZE) < 0) { + THROW_ERROR("munmap failed"); + } + + // Unlink the shared memory object + shm_unlink(SHM_OBJ); + return 0; +} + +int consumer_process() +{ + // Shared memory file descriptor + int shm_fd; + // Shared memory buffer + void *shm_buf; + + // Create the shared memory object + shm_fd = shm_open(SHM_OBJ, O_CREAT | O_RDWR, 0666); + if (shm_fd < 0) { + THROW_ERROR("shm_open failed"); + } + + // Configure the size of the shared memory object + if (ftruncate(shm_fd, SHM_SIZE) < 0) { + THROW_ERROR("ftruncate error"); + } + + // Memory map the shared memory object + shm_buf = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, 0); + if (shm_buf == MAP_FAILED) { + THROW_ERROR("mmap(MAP_SHARED) failed"); + } + + while (1) { + if (strncmp(shm_buf, MSG0, MSG_SIZE) != 0) { + sleep(1); + continue; + } + printf("[Consumer] receive %s\n", MSG0); + strncpy(shm_buf, MSG1, MSG_SIZE); + printf("[Consumer] send %s\n", MSG1); + while (1) { + if (strncmp(shm_buf, MSG2, MSG_SIZE) != 0) { + sleep(1); + continue; + } + printf("[Consumer] receive %s\n", MSG2); + strncpy(shm_buf, MSG3, MSG_SIZE); + printf("[Consumer] send %s\n", MSG3); + break; + } + break; + } + + // Unmap the shared memory + if (munmap(shm_buf, SHM_SIZE) < 0) { + THROW_ERROR("munmap failed"); + } + + // Unlink the shared memory object + shm_unlink(SHM_OBJ); + return 0; +} + +// ============================================================================ +// Test entry +// ============================================================================ + +int main(int argc, const char *argv[]) +{ + if (argc == 1) { + // Producer side + return producer_process(); + } else { + // Consumer side + return consumer_process(); + } +}