1 /*
2  *   Copyright (C) Bull S.A. 1996
3  *   Copyright (c) International Business Machines  Corp., 2001
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
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 /*---------------------------------------------------------------------+
20 |                           shmem_test_01                              |
21 | ==================================================================== |
22 |                                                                      |
23 | Description:  Simplistic test to verify the shmem system function    |
24 |               calls.                                                 |
25 |                                                                      |
26 |                                                                      |
27 | Algorithm:    o  Obtain a unique shared memory identifier with       |
28 |                  shmget ()                                           |
29 |               o  Map the shared memory segment to the current        |
30 |                  process with shmat ()                               |
31 |               o  Index through the shared memory segment             |
32 |               o  Release the shared memory segment with shmctl ()    |
33 |                                                                      |
34 | System calls: The following system calls are tested:                 |
35 |                                                                      |
36 |               shmget () - Gets shared memory segments                |
37 |               shmat () - Controls shared memory operations           |
38 |               shmctl () - Attaches a shared memory segment or mapped |
39 |                           file to the current process                |
40 |                                                                      |
41 | Usage:        shmem_test_01                                          |
42 |                                                                      |
43 | To compile:   cc -o shmem_test_01 shmem_test_01.c                    |
44 |                                                                      |
45 | Last update:   Ver. 1.2, 2/8/94 00:08:30                           |
46 |                                                                      |
47 | Change Activity                                                      |
48 |                                                                      |
49 |   Version  Date    Name  Reason                                      |
50 |    0.1     111593  DJK   Initial version for AIX 4.1                 |
51 |    1.2     020794  DJK   Moved to "prod" directory                   |
52 |                                                                      |
53 +---------------------------------------------------------------------*/
54 
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59 #include <errno.h>
60 #include <sys/shm.h>
61 
62 /* Defines
63  *
64  * MAX_SHMEM_SIZE: maximum shared memory segment size of 256MB
65  * (reference 3.2.5 man pages)
66  *
67  * DEFAULT_SHMEM_SIZE: default shared memory size, unless specified with
68  * -s command line option
69  *
70  * SHMEM_MODE: shared memory access permissions (permit process to read
71  * and write access)
72  *
73  * USAGE: usage statement
74  */
75 #define MAX_SHMEM_SIZE		256*1024*1024
76 #define DEFAULT_SHMEM_SIZE	1024*1024
77 #define	SHMEM_MODE		(SHM_R | SHM_W)
78 #define USAGE	"\nUsage: %s [-s shmem_size]\n\n" \
79 		"\t-s shmem_size  size of shared memory segment (bytes)\n" \
80 		"\t               (must be less than 256MB!)\n\n"
81 
82 /*
83  * Function prototypes
84  *
85  * parse_args (): Parse command line arguments
86  * sys_error (): System error message function
87  * error (): Error message function
88  */
89 void parse_args(int, char **);
90 void sys_error(const char *, int);
91 void error(const char *, int);
92 
93 /*
94  * Global variables
95  *
96  * shmem_size: shared memory segment size (in bytes)
97  */
98 int shmem_size = DEFAULT_SHMEM_SIZE;
99 
100 /*---------------------------------------------------------------------+
101 |                               main                                   |
102 | ==================================================================== |
103 |                                                                      |
104 |                                                                      |
105 | Function:  Main program  (see prolog for more details)               |
106 |                                                                      |
107 | Returns:   (0)  Successful completion                                |
108 |            (-1) Error occurred                                       |
109 |                                                                      |
110 +---------------------------------------------------------------------*/
main(int argc,char ** argv)111 int main(int argc, char **argv)
112 {
113 	int shmid;		/* (Unique) Shared memory identifier */
114 	char *shmptr,		/* Shared memory segment address */
115 	*ptr,			/* Index into shared memory segment */
116 	 value = 0;		/* Value written into shared memory segment */
117 
118 	/*
119 	 * Parse command line arguments and print out program header
120 	 */
121 	parse_args(argc, argv);
122 	printf("%s: IPC Shared Memory TestSuite program\n", *argv);
123 
124 	/*
125 	 * Obtain a unique shared memory identifier with shmget ().
126 	 * Attach the shared memory segment to the process with shmat (),
127 	 * index through the shared memory segment, and then release the
128 	 * shared memory segment with shmctl ().
129 	 */
130 	printf("\n\tGet shared memory segment (%d bytes)\n", shmem_size);
131 	if ((shmid = shmget(IPC_PRIVATE, shmem_size, SHMEM_MODE)) < 0)
132 		sys_error("shmget failed", __LINE__);
133 
134 	printf("\n\tAttach shared memory segment to process\n");
135 	if ((shmptr = shmat(shmid, 0, 0)) < 0)
136 		sys_error("shmat failed", __LINE__);
137 
138 	printf("\n\tIndex through shared memory segment ...\n");
139 	for (ptr = shmptr; ptr < (shmptr + shmem_size); ptr++)
140 		*ptr = value++;
141 
142 	printf("\n\tRelease shared memory\n");
143 	if (shmctl(shmid, IPC_RMID, 0) < 0)
144 		sys_error("shmctl failed", __LINE__);
145 
146 	/*
147 	 * Program completed successfully -- exit
148 	 */
149 	printf("\nsuccessful!\n");
150 
151 	return (0);
152 }
153 
154 /*---------------------------------------------------------------------+
155 |                             parse_args ()                            |
156 | ==================================================================== |
157 |                                                                      |
158 | Function:  Parse the command line arguments & initialize global      |
159 |            variables.                                                |
160 |                                                                      |
161 | Updates:   (command line options)                                    |
162 |                                                                      |
163 |            [-s] size: shared memory segment size                     |
164 |                                                                      |
165 +---------------------------------------------------------------------*/
parse_args(int argc,char ** argv)166 void parse_args(int argc, char **argv)
167 {
168 	int i;
169 	int errflag = 0;
170 	char *program_name = *argv;
171 	extern char *optarg;	/* Command line option */
172 
173 	while ((i = getopt(argc, argv, "s:?")) != EOF) {
174 		switch (i) {
175 		case 's':
176 			shmem_size = atoi(optarg);
177 			break;
178 		case '?':
179 			errflag++;
180 			break;
181 		}
182 	}
183 
184 	if (shmem_size < 1 || shmem_size > MAX_SHMEM_SIZE)
185 		errflag++;
186 
187 	if (errflag) {
188 		fprintf(stderr, USAGE, program_name);
189 		exit(2);
190 	}
191 }
192 
193 /*---------------------------------------------------------------------+
194 |                             sys_error ()                             |
195 | ==================================================================== |
196 |                                                                      |
197 | Function:  Creates system error message and calls error ()           |
198 |                                                                      |
199 +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)200 void sys_error(const char *msg, int line)
201 {
202 	char syserr_msg[256];
203 
204 	sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
205 	error(syserr_msg, line);
206 }
207 
208 /*---------------------------------------------------------------------+
209 |                               error ()                               |
210 | ==================================================================== |
211 |                                                                      |
212 | Function:  Prints out message and exits...                           |
213 |                                                                      |
214 +---------------------------------------------------------------------*/
error(const char * msg,int line)215 void error(const char *msg, int line)
216 {
217 	fprintf(stderr, "ERROR [line: %d] %s\n", line, msg);
218 	exit(-1);
219 }
220