Inizio della shared memory
[gapil.git] / sources / SharedMem.c
index 23f9c097d30cec89a4953586a25bd73f60550729..35ba20caa2a3c323ea05fbdc7727c9b53ee2a42e 100644 (file)
 /***************************************************************
  *
  * File SharedMem.c 
- * Routine for Shared Memory use
+ * Routines for Shared Memory use. 
+ *
+ * Define two interfaces, the first one use SysV shared memory, the
+ * second POSIX shared memory.
  *
  * Author: S. Piccardi
  *
- * $Id: SharedMem.c,v 1.2 2002/12/03 22:30:11 piccardi Exp $
+ * $Id: SharedMem.c,v 1.4 2003/02/03 14:27:58 piccardi Exp $
  *
  ***************************************************************/
 #include <sys/shm.h>                  /* SysV IPC shared memory declarations */
 #include <stdio.h>                                 /* standard I/O functions */
 #include <fcntl.h>
 #include <signal.h>                          /* signal handling declarations */
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+
+#include "macros.h"
+/* *************************************************************************
+ *
+ *  Functions for SysV shared memory
+ *
+ * ************************************************************************* */
 /*
  * Function ShmCreate:
  * Create and attach a SysV shared memory segment to the current process.
  *
  * Input:  an IPC key value
  *         the shared memory segment size
- * Return: the address of the segment
+ *         the permissions
+ *         the fill value
+ * Return: the address of the shared memory segment (NULL on error)
  */
-void * ShmCreate(key_t ipc_key, int shm_size, char fill) 
+void * ShmCreate(key_t ipc_key, int shm_size, int perm, char fill) 
 {
-    void * shptr;
-    int shmid;                        /* ID of the IPC shared memory segment */
-    shmid = shmget(ipc_key,shm_size,IPC_CREAT|0666);           /* get shm ID */
-    if (shmid < 0) { 
-       return (void *) shmid;
+    void * shm_ptr;
+    int shm_id;                       /* ID of the IPC shared memory segment */
+    shm_id = shmget(ipc_key, shm_size, IPC_CREAT|perm);        /* get shm ID */
+    if (shm_id < 0) { 
+       return NULL;
     }
-    shptr = shmat(shmid,0,0);                      /* take the pointer to it */
-    if ( shptr == 0 ){    
-        perror("cannot attach shared memory");
-       exit(1);
+    shm_ptr = shmat(shm_id, NULL, 0);                  /* map it into memory */
+    if (shm_ptr < 0) {
+       return NULL;
     }
-    memset((void *)shptr, fill, shm_size); /* second counter starts from "0" */
-    return shptr;
+    memset((void *)shm_ptr, fill, shm_size);                 /* fill segment */
+    return shm_ptr;
 }
 /*
  * Function ShmFind:
- * Find a shared memory segment 
+ * Find a SysV shared memory segment 
  * Input:  an IPC key value
  *         the shared memory segment size
- * Return: the address of the segment
+ * Return: the address of the segment (NULL on error)
  */
 void * ShmFind(key_t ipc_key, int shm_size) 
 {
-    void * shptr;
-    int shmid;               /* ID of the IPC shared memory segment */
-    if ( (shmid=shmget(ipc_key,shm_size,0))<0 ){  /* find shared memory ID */
-        perror("cannot find shared memory");
-        exit(1);
+    void * shm_ptr;
+    int shm_id;                      /* ID of the SysV shared memory segment */
+    shm_id = shmget(ipc_key, shm_size, 0);          /* find shared memory ID */
+    if (shm_id < 0) {
+       return NULL;
+    }
+    shm_ptr = shmat(shm_id, NULL, 0);                  /* map it into memory */
+    if (shm_ptr < 0) {
+       return NULL;
+    }
+    return shm_ptr;
+}
+/*
+ * Function ShmRemove:
+ * Scheudle removal for a SysV shared memory segment 
+ * Input:  an IPC key value
+ *         the shared memory segment size
+ * Return: 0 on success, -1 on error
+ */
+int ShmRemove(key_t ipc_key, void * shm_ptr) 
+{
+    int shm_id;                      /* ID of the SysV shared memory segment */
+    /* first detach segment */
+    if (shmdt(shm_ptr) < 0) {
+       return -1;
+    }
+    /* schedule segment removal */
+    shm_id = shmget(ipc_key, 0, 0);                 /* find shared memory ID */
+    if (shm_id < 0) {
+       if (errno == EIDRM) return 0;
+       return -1;
     }
-    if ( (shptr=shmat(shmid,0,0)) < 0 ){    /* take the pointer to it */
-        perror("cannot attach shared memory");
-        exit(1);
+    if (shmctl(shm_id, IPC_RMID, NULL) < 0) {             /* ask for removal */
+       if (errno == EIDRM) return 0;
+       return -1;
     }
-    return shptr;
+    return 0;
+}
+/* *************************************************************************
+ *
+ *  Functions for POSIX shared memory
+ *
+ * ************************************************************************* */
+/*
+ * Function CreateShm:
+ * Create a POSIX shared memory segment and map it to the current process.
+ *
+ *
+ * Input:  a pathname
+ *         the shared memory segment size
+ *         the permissions
+ *         the fill value
+ * Return: the address of the shared memory segment (NULL on error)
+ */
+void * CreateShm(char * shm_name, off_t shm_size, mode_t perm, char fill) 
+{
+    void * shm_ptr;
+    int fd;
+    int flag;
+    /* first open the object, creating it if not existent */
+    flag = O_CREAT|O_EXCL|O_RDWR;
+    fd = shm_open(shm_name, flag, perm);    /* get object file descriptor */
+    if (fd < 0) { 
+       perror("errore in shm_open");
+       return NULL;
+    }
+    /* set the object size */
+    if (ftruncate(fd, shm_size)) {
+       perror("errore in ftruncate");
+       return NULL;
+    }
+    /* map it in the process address space */
+    shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
+    if (shm_ptr == MAP_FAILED) {
+       perror("errore in mmap");
+       return NULL;
+    }
+    memset((void *) shm_ptr, fill, shm_size);                /* fill segment */
+    return shm_ptr;
+}
+/*
+ * Function FindShm:
+ * Find a POSIX shared memory segment 
+ * Input:  a name
+ *         the shared memory segment size
+ * Return: the address of the segment (NULL on error)
+ */
+void * FindShm(char * shm_name, off_t shm_size) 
+{
+    void * shm_ptr;
+    int fd;                           /* ID of the IPC shared memory segment */
+    /* find shared memory ID */
+    if ((fd = shm_open(shm_name, O_RDWR|O_EXCL, 0)) < 0) {
+       debug("Cannot open %s\n", shm_name);
+       return NULL;
+    }
+    /* take the pointer to it */
+    shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
+    if (shm_ptr == MAP_FAILED) {
+       return NULL;
+    }
+    return shm_ptr;
+}
+/*
+ * Function RemoveShm:
+ * Remove a POSIX shared memory segment 
+ * Input:  the object name
+ * Return: 0 on success, -1 on error
+ */
+int RemoveShm(char * shm_name)
+{
+    shm_unlink(shm_name);
+    return 0;
 }