--- a +++ b/SimpleShmExample/main.c @@ -0,0 +1,188 @@ +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> + +#include <sys/mman.h> +#include <sys/types.h> + +#include <stdint.h> + #include <string.h> + + void printUsage(); + + typedef int bool; + #define true 1 + #define false 0 + +int main( int argc, const char* argv[] ) +{ + // args parsing + bool xGet = false; + bool xSet = false; + bool xReset = false; + uint16_t uiSetValue = 0; + { + // pares args + char opt; + while((opt = getopt(argc, (char * const*)argv, "srgh")) != -1) + { + switch(opt) + { + case 's': // set + xSet = true; + break; + case 'r': // reset + xReset = true; + break; + case 'g': // get + xGet = true; + break; + case 'h': // help + printUsage(); + return 0; + break; + default: + printf("invalid opt: %s\n", opt); + printUsage(); + return -1; + } + } + + // check that only one option is used + if ((xGet && xSet) || (xGet && xReset) || (xSet && xReset)) + { + printf("Only one option at a time!\n"); + printUsage(); + return -2; + } + + // if no option selected, assume get + if (!(xGet || xSet || xReset)) + xGet = true; + + // optind is for the extra arguments + // which are not parsed + if (!xSet && optind < argc) + { + // only set expects additional arguments + printf("unexpected extra argument: %s\n", argv[optind]); + printUsage(); + return -3; + } + else if ((optind + 1) < argc) + { + // set only expects one extra argument + printf("unexpected extra argument: %s\n", argv[optind+1]); + printUsage(); + return -4; + } + else if (xSet) + { + printf("extra argument for set: %s\n", argv[optind]); + if (!sscanf(argv[optind], "%hd", &uiSetValue)) + { + printf("unable to parse the number: %s\n", argv[optind]); + return -5; + } + } + } + +/* ******************************************** + * Actual shared memory code + **********************************************/ + + char pszName[] = "CodesysShared"; + uint16_t uiCounter = 0; + size_t shmSize = sizeof(uiCounter); + int shmfd; // shared memory handle + bool xShmWasCreated = false; + void *pshm = NULL; + // try to open shm + { + shmfd = shm_open(pszName, O_RDWR, S_IRWXU | S_IRWXG); + + if (shmfd < 0) + { + /* creating a new shared memory object because it does not exist*/ + printf("creating new shm\n"); + shmfd = shm_open(pszName, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG); /* returns a file handle -- O_EXCL */ + xShmWasCreated = true; + } + + if (shmfd < 0) + { + printf("failed to execute shm_open() : %d\n", shmfd); + + return 1; + } + + // adjust the mapped file size + if (ftruncate(shmfd, shmSize) < 0) + { + printf("ftruncate() failed\n"); + close(shmfd); + return 2; + } + + /* requesting the shared segment -- mmap() + void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); */ + pshm = mmap(0, shmSize, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0); + if (pshm == MAP_FAILED) + { + printf("mmap() failed: %s\n", strerror(errno)); + close(shmfd); + return 3; + } + + printf("shared memory open\n"); + + if (xShmWasCreated) + { + /* shared memory is new, so set it to 0 */ + memset(pshm,0,sizeof(uiCounter)); + printf("Shm was new, set it to 0.\n"); + } + } +/* ************************************* + * Accessing the shared memory + ***************************************/ + + uint16_t *pCounter = (uint16_t *)pshm; + + // always read the value and print it + uiCounter = *pCounter; + printf("counter is %d\n", uiCounter); + + if (xReset) + { + uiCounter = 0; // set local copy + *pCounter = uiCounter; // set actual shm + printf("reset the counter!\n"); + } + else if (xSet) + { + uiCounter = uiSetValue; // set local copy + *pCounter = uiCounter; // set actual shm + printf("Set the counter to: %d\n", uiCounter); + } + + // close the shared memory + munmap(pshm,shmSize); + close(shmfd); + + return 0; +} + +void printUsage() +{ + printf("program [-g | -s number | -r | -h]\n"); + printf("default: -g\n"); + printf("-g : get counter\n"); + printf("-s number : set counter to number\n"); + printf("-r : reset counter\n"); + printf("-h : print usage\n"); +}