Iniziato a lavorare sulla Shared Memory POSIX. Risistemate un po' di cose
[gapil.git] / sources / SharedMem.c
1 /* SharedMem.c
2  * 
3  * Copyright (C) 2002 Simone Piccardi
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /***************************************************************
20  *
21  * File SharedMem.c 
22  * Routines for Shared Memory use. 
23  *
24  * Define two interfaces, the first one use SysV shared memory, the
25  * second POSIX shared memory.
26  *
27  * Author: S. Piccardi
28  *
29  * $Id: SharedMem.c,v 1.3 2003/02/02 20:35:33 piccardi Exp $
30  *
31  ***************************************************************/
32 #include <sys/shm.h>                  /* SysV IPC shared memory declarations */
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <stdio.h>                                 /* standard I/O functions */
36 #include <fcntl.h>
37 #include <signal.h>                          /* signal handling declarations */
38 #include <unistd.h>
39 #include <sys/mman.h>
40 #include <string.h>
41 #include <errno.h>
42 /* *************************************************************************
43  *
44  *  Functions for SysV shared memory
45  *
46  * ************************************************************************* */
47 /*
48  * Function ShmCreate:
49  * Create and attach a SysV shared memory segment to the current process.
50  *
51  * First call get a shared memory segment with KEY key access and size SIZE,
52  * by creating it with R/W privilege for the user (this is the meaning of
53  * the ored flags). The function return an identifier shmid used for any 
54  * further reference to the shared memory segment. 
55  * Second call attach the shared memory segment to this process and return a
56  * pointer to it (of void * type). 
57  * Then initialize shared memory to the given value
58  *
59  * Input:  an IPC key value
60  *         the shared memory segment size
61  *         the permissions
62  *         the fill value
63  * Return: the address of the shared memory segment (NULL on error)
64  */
65 void * ShmCreate(key_t ipc_key, int shm_size, int perm, char fill) 
66 {
67     void * shm_ptr;
68     int shm_id;                       /* ID of the IPC shared memory segment */
69     shm_id = shmget(ipc_key, shm_size, IPC_CREAT|perm);        /* get shm ID */
70     if (shm_id < 0) { 
71         return NULL;
72     }
73     shm_ptr = shmat(shm_id, NULL, 0);                  /* map it into memory */
74     if (shm_ptr < 0) {
75         return NULL;
76     }
77     memset((void *)shm_ptr, fill, shm_size);                 /* fill segment */
78     return shm_ptr;
79 }
80 /*
81  * Function ShmFind:
82  * Find a SysV shared memory segment 
83  * Input:  an IPC key value
84  *         the shared memory segment size
85  * Return: the address of the segment (NULL on error)
86  */
87 void * ShmFind(key_t ipc_key, int shm_size) 
88 {
89     void * shm_ptr;
90     int shm_id;                      /* ID of the SysV shared memory segment */
91     shm_id = shmget(ipc_key, shm_size, 0);          /* find shared memory ID */
92     if (shm_id < 0) {
93         return NULL;
94     }
95     shm_ptr = shmat(shm_id, NULL, 0);                  /* map it into memory */
96     if (shm_ptr < 0) {
97         return NULL;
98     }
99     return shm_ptr;
100 }
101 /*
102  * Function ShmRemove:
103  * Scheudle removal for a SysV shared memory segment 
104  * Input:  an IPC key value
105  *         the shared memory segment size
106  * Return: 0 on success, -1 on error
107  */
108 int ShmRemove(key_t ipc_key, void * shm_ptr) 
109 {
110     int shm_id;                      /* ID of the SysV shared memory segment */
111     /* first detach segment */
112     if (shmdt(shm_ptr) < 0) {
113         return -1;
114     }
115     /* schedule segment removal */
116     shm_id = shmget(ipc_key, 0, 0);                 /* find shared memory ID */
117     if (shm_id < 0) {
118         if (errno == EIDRM) return 0;
119         return -1;
120     }
121     if (shmctl(shm_id, IPC_RMID, NULL) < 0) {             /* ask for removal */
122         if (errno == EIDRM) return 0;
123         return -1;
124     }
125     return 0;
126 }
127 /* *************************************************************************
128  *
129  *  Functions for POSIX shared memory
130  *
131  * ************************************************************************* */
132 /*
133  * Function CreateShm:
134  * Create a POSIX shared memory segment and map it to the current process.
135  *
136  *
137  * Input:  a pathname
138  *         the shared memory segment size
139  *         the permissions
140  *         the fill value
141  * Return: the address of the shared memory segment (NULL on error)
142  */
143 void * CreateShm(char * shm_name, int shm_size, int perm, char fill) 
144 {
145     void * shm_ptr;
146     int fd;
147     int flag;
148     /* first open the object, creating it if not existent */
149     flag = O_RDWR|O_TRUNC|O_CREAT|O_EXCL;
150     fd = shm_open(shm_name, flag, perm);    /* get object file descriptor */
151     if (fd < 0) { 
152         return NULL;
153     }
154     /* set the object size */
155     if (ftruncate(fd, shm_size)) {
156         return NULL;
157     }
158     /* map it in the process address space */
159     shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
160     if (shm_ptr == MAP_FAILED) {
161         return NULL;
162     }
163     memset((void *) shm_ptr, fill, shm_size);                /* fill segment */
164     return shm_ptr;
165 }
166 /*
167  * Function FindShm:
168  * Find a POSIX shared memory segment 
169  * Input:  a name
170  *         the shared memory segment size
171  * Return: the address of the segment (NULL on error)
172  */
173 void * FindShm(char * shm_name, int shm_size) 
174 {
175     void * shm_ptr;
176     int fd;                           /* ID of the IPC shared memory segment */
177     /* find shared memory ID */
178     if ((fd = shm_open(shm_name, O_RDWR|O_EXCL, 0)) < 0) {
179         return NULL;
180     }
181     /* take the pointer to it */
182     shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
183     if (shm_ptr == MAP_FAILED) {
184         return NULL;
185     }
186     return shm_ptr;
187 }
188 /*
189  * Function RemoveShm:
190  * Remove a POSIX shared memory segment 
191  * Input:  the object name
192  * Return: 0 on success, -1 on error
193  */
194 int RemoveShm(char * shm_name)
195 {
196     shm_unlink(shm_name);
197     return 0;
198 }