1 /*
2 * Copyright (C) Bull S.A. 1996
3 * Copyright (c) International Business Machines Corp., 2001
4 * Copyright (C) 2008 CAI Qian <caiqian@cclom.cn>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 * the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21 /*---------------------------------------------------------------------+
22 | shmem_test_06.c |
23 | ==================================================================== |
24 | Title: Segment Register 0xE |
25 | |
26 | Purpose: simultaneous attachment of more than ten shared |
27 | memory regions to a process. Using segment registers |
28 | 0x3 to 0xC and 0xE . |
29 | |
30 | Description: Simplistic test to verify that a process can obtain |
31 | 11 shared memory regions. |
32 | |
33 | |
34 | Algorithm: * from 1 up to 11 |
35 | { |
36 | o Create a key to uniquely identify the shared segment|
37 | using ftok() subroutine. |
38 | o Obtain a unique shared memory identifier with |
39 | shmget () |
40 | o Map the shared memory segment to the current |
41 | process with shmat () |
42 | o Index through the shared memory segment |
43 | } |
44 | * from 1 up to 11 |
45 | { |
46 | o Detach from the segment with shmdt() |
47 | o Release the shared memory segment with shmctl () |
48 | } |
49 | |
50 | System calls: The following system calls are tested: |
51 | |
52 | ftok() |
53 | shmget () |
54 | shmat () |
55 | shmdt () |
56 | shmctl () |
57 | |
58 | Usage: shmem_test_06 |
59 | |
60 | To compile: cc -O -g shmem_test_06.c -o shmem_test_06 -lbsd |
61 | |
62 | Last update: |
63 | |
64 | Change Activity |
65 | |
66 | Version Date Name Reason |
67 | 0.1 010797 J.Malcles initial version for 4.2.G |
68 | |
69 | |
70 +---------------------------------------------------------------------*/
71
72 #include <stdio.h>
73 #include <stdlib.h>
74 #include <string.h>
75 #include <errno.h>
76 #include <unistd.h>
77 #include <sys/shm.h>
78
79 #include <sys/types.h>
80 #include <sys/ipc.h>
81
82 #include <sys/stat.h>
83 int offsets_cnt = 11;
84 /* Defines
85 *
86 * MAX_SHMEM_SIZE: maximum shared memory segment size of 256MB
87 *
88 * MAX_SHMEM_NUMBER: maximum number of simultaneous attached shared memory
89 * regions
90 *
91 * DEFAULT_SHMEM_SIZE: default shared memory size, unless specified with
92 * -s command line option
93 *
94 * SHMEM_MODE: shared memory access permissions (permit process to read
95 * and write access)
96 *
97 * USAGE: usage statement
98 */
99 #define MAX_SHMEM_SIZE 256*1024*1024
100 #define MAX_SHMEM_NUMBER 11
101 #define DEFAULT_SHMEM_SIZE 1024*1024
102 #define SHMEM_MODE (SHM_R | SHM_W)
103 #define USAGE "\nUsage: %s [-s shmem_size]\n\n" \
104 "\t-s shmem_size size of shared memory segment (bytes)\n" \
105 "\t (must be less than 256MB!)\n\n"
106
107 #define GOTHERE printf("got to line %d\n", __LINE__);
108
109 /*
110 * Function prototypes
111 *
112 * parse_args (): Parse command line arguments
113 * sys_error (): System error message function
114 * error (): Error message function
115 */
116 void parse_args(int, char **);
117 void sys_error(const char *, int);
118 void error(const char *, int);
119
120 /*
121 * Global variables
122 *
123 * shmem_size: shared memory segment size (in bytes)
124 */
125 int shmem_size = DEFAULT_SHMEM_SIZE;
126
127 /*---------------------------------------------------------------------+
128 | main |
129 | ==================================================================== |
130 | |
131 | |
132 | Function: Main program (see prolog for more details) |
133 | |
134 | Returns: (0) Successful completion |
135 | (-1) Error occurred |
136 | |
137 +---------------------------------------------------------------------*/
main(int argc,char ** argv)138 int main(int argc, char **argv)
139 {
140 int i;
141
142 int shmid[MAX_SHMEM_NUMBER]; /* (Unique) Shared memory identifier */
143
144 char *shmptr[MAX_SHMEM_NUMBER]; /* Shared memory segment address */
145 char *ptr; /* Index into shared memory segment */
146
147 int value = 0; /* Value written into shared memory segment */
148
149 key_t mykey[MAX_SHMEM_NUMBER];
150 char *null_file = "/dev/null";
151 char proj[MAX_SHMEM_NUMBER] = {
152 '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'E'
153 };
154
155 /*
156 * Parse command line arguments and print out program header
157 */
158 parse_args(argc, argv);
159 printf("%s: IPC Shared Memory TestSuite program\n", *argv);
160
161 for (i = 0; i < offsets_cnt; i++) {
162 char tmpstr[256];
163 /*
164 * Create a key to uniquely identify the shared segment
165 */
166
167 mykey[i] = ftok(null_file, proj[i]);
168
169 printf
170 ("\n\tmykey to uniquely identify the shared memory segment 0x%x\n",
171 mykey[i]);
172
173 printf("\n\tGet shared memory segment (%d bytes)\n",
174 shmem_size);
175 /*
176 * Obtain a unique shared memory identifier with shmget ().
177 */
178
179 if ((long)
180 (shmid[i] =
181 shmget(mykey[i], shmem_size, IPC_CREAT | 0666)) < 0)
182 sys_error("shmget failed", __LINE__);
183
184 printf("\n\tAttach shared memory segment to process\n");
185
186 if ((long)(shmptr[i] = shmat(shmid[i], NULL, 0)) == -1) {
187 /* If shmat(2) failed, we need the currect process address
188 space layout to debug. The failure can be random. */
189 sprintf(tmpstr, "cat /proc/%d/maps >&2", (int)getpid());
190 fprintf(stderr, "heap %p\n", sbrk(0));
191 system(tmpstr);
192
193 sprintf(tmpstr, "shmat failed - return: %ld",
194 (long)shmptr[i]);
195 sys_error(tmpstr, __LINE__);
196 }
197
198 printf("\n\tShared memory segment address : %p \n", shmptr[i]);
199
200 printf("\n\tIndex through shared memory segment ...\n");
201
202 /*
203 * Index through the shared memory segment
204 */
205
206 for (ptr = shmptr[i]; ptr < (shmptr[i] + shmem_size); ptr++)
207 *ptr = value++;
208
209 } // for 1..11
210
211 printf("\n\tDetach from the segment using the shmdt subroutine\n");
212
213 printf("\n\tRelease shared memory\n");
214
215 for (i = 0; i < offsets_cnt; i++) {
216 // Detach from the segment
217
218 shmdt(shmptr[i]);
219
220 // Release shared memory
221
222 if (shmctl(shmid[i], IPC_RMID, 0) < 0)
223 sys_error("shmctl failed", __LINE__);
224
225 } // 2nd for 1..11
226 /*
227 * Program completed successfully -- exit
228 */
229
230 printf("\nsuccessful!\n");
231
232 return (0);
233
234 }
235
236 /*---------------------------------------------------------------------+
237 | parse_args () |
238 | ==================================================================== |
239 | |
240 | Function: Parse the command line arguments & initialize global |
241 | variables. |
242 | |
243 | Updates: (command line options) |
244 | |
245 | [-s] size: shared memory segment size |
246 | |
247 +---------------------------------------------------------------------*/
parse_args(int argc,char ** argv)248 void parse_args(int argc, char **argv)
249 {
250 int i;
251 int errflag = 0;
252 char *program_name = *argv;
253 extern char *optarg; /* Command line option */
254
255 while ((i = getopt(argc, argv, "s:?")) != EOF) {
256 switch (i) {
257 case 's':
258 shmem_size = atoi(optarg);
259 break;
260 case '?':
261 errflag++;
262 break;
263 }
264 }
265
266 if (shmem_size < 1 || shmem_size > MAX_SHMEM_SIZE)
267 errflag++;
268
269 if (errflag) {
270 fprintf(stderr, USAGE, program_name);
271 exit(2);
272 }
273 }
274
275 /*---------------------------------------------------------------------+
276 | sys_error () |
277 | ==================================================================== |
278 | |
279 | Function: Creates system error message and calls error () |
280 | |
281 +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)282 void sys_error(const char *msg, int line)
283 {
284 char syserr_msg[256];
285
286 sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
287 error(syserr_msg, line);
288 }
289
290 /*---------------------------------------------------------------------+
291 | error () |
292 | ==================================================================== |
293 | |
294 | Function: Prints out message and exits... |
295 | |
296 +---------------------------------------------------------------------*/
error(const char * msg,int line)297 void error(const char *msg, int line)
298 {
299 fprintf(stderr, "ERROR [line: %d] %s\n", line, msg);
300 exit(-1);
301 }
302