+/* SharedMem.c
+ *
+ * Copyright (C) 2002 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
/***************************************************************
*
* 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.1 2002/12/03 11:06:05 piccardi Exp $
+ * $Id: SharedMem.c,v 1.8 2003/05/02 09:55:14 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, int 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:
+ * Schedule 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 (shmctl(shm_id, IPC_RMID, NULL) < 0) { /* ask for removal */
+ if (errno == EIDRM) return 0;
+ return -1;
+ }
+ 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, int 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;
}
- if ( (shptr=shmat(shmid,0,0)) < 0 ){ /* take the pointer to it */
- perror("cannot attach shared memory");
- exit(1);
+ /* 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 shptr;
+ 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)
+{
+ return shm_unlink(shm_name);
}