2 * Copyright (c) 2000 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 /**************************************************************
20 * OS Testing - Silicon Graphics, Inc.
22 * FUNCTION NAME : forker
25 * FUNCTION TITLE : fork desired number of copies of the current process
26 * fork a process and return control to caller
29 * int forker(ncopies, mode, prefix)
34 * int background(prefix);
37 * extern int Forker_pids[];
38 * extern int Forker_npids;
40 * AUTHOR : Richard Logan
42 * CO-PILOT(s) : Dean Roehrich
44 * INITIAL RELEASE : UNICOS 8.0
47 * The background function will do a fork of the current process.
48 * The parent process will then exit, thus orphaning the
49 * child process. Doing this will not nice the child process
50 * like executing a cmd in the background using "&" from the shell.
51 * If the fork fails and prefix is not NULL, a error message is printed
52 * to stderr and the process will exit with a value of errno.
54 * The forker function will fork <ncopies> minus one copies
55 * of the current process. There are two modes in how the forks
56 * will be done. Mode 0 (default) will have all new processes
57 * be childern of the parent process. Using Mode 1,
58 * the parent process will have one child and that child will
59 * fork the next process, if necessary, and on and on.
60 * The forker function will return the number of successful
61 * forks. This value will be different for the parent and each child.
62 * Using mode 0, the parent will get the total number of successful
63 * forks. Using mode 1, the newest child will get the total number
64 * of forks. The parent will get a return value of 1.
66 * The forker function also updates the global variables
67 * Forker_pids[] and Forker_npids. The Forker_pids array will
68 * be updated to contain the pid of each new process. The
69 * Forker_npids variable contains the number of entries
70 * in Forker_pids. Note, not all processes will have
71 * access to all pids via Forker_pids. If using mode 0, only the
72 * parent process and the last process will have all information.
73 * If using mode 1, only the last child process will have all information.
75 * If the prefix parameter is not NULL and the fork system call fails,
76 * a error message will be printed to stderr. The error message
77 * the be preceeded with prefix string. If prefix is NULL,
78 * no error message is printed.
80 * SPECIAL REQUIREMENTS
84 * This should contain the description, author, and date of any
85 * "interesting" modifications (i.e. info should helpful in
86 * maintaining/enhancing this module).
87 * username description
88 * ----------------------------------------------------------------
89 * rrl This functions will first written during
90 * the SFS testing days, 1993.
93 * The child pids are stored in the fixed array, Forker_pids.
94 * The array only has space for 4098 pids. Only the first
95 * 4098 pids will be stored in the array.
97 **************************************************************/
101 #include <unistd.h> /* fork, getpid, sleep */
103 #include <stdlib.h> /* exit */
106 int Forker_pids[FORKER_MAX_PIDS]; /* holds pids of forked processes */
107 int Forker_npids=0; /* number of entries in Forker_pids */
109 /***********************************************************************
111 * This function will fork and the parent will exit zero and
112 * the child will return. This will orphan the returning process
113 * putting it in the background.
116 * 0 : if fork did not fail
117 * !0 : if fork failed, the return value will be the errno.
118 ***********************************************************************/
125 if ( prefix != NULL )
126 fprintf(stderr, "%s: In %s background(), fork() failed, errno:%d %s\n",
127 prefix, __FILE__, errno, strerror(errno));
130 case 0: /* child process */
139 } /* end of background */
141 /***********************************************************************
142 * Forker will fork ncopies-1 copies of self.
144 ***********************************************************************/
146 forker(ncopies, mode, prefix)
148 int mode; /* 0 - all childern of parent, 1 - only 1 direct child */
149 char *prefix; /* if ! NULL, an message will be printed to stderr */
150 /* if fork fails. The prefix (program name) will */
151 /* preceed the message */
159 for ( cnt=1; cnt < ncopies; cnt++ ) {
162 case 1 : /* only 1 direct child */
163 if ( (pid = fork()) == -1 ) {
164 if ( prefix != NULL )
165 fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
166 prefix, __FILE__, errno, strerror(errno));
172 case 0: /* child - continues the forking */
174 if ( Forker_npids < FORKER_MAX_PIDS )
175 Forker_pids[Forker_npids-1]=getpid();
178 default: /* parent - stop the forking */
179 if ( Forker_npids < FORKER_MAX_PIDS )
180 Forker_pids[Forker_npids-1]=pid;
186 default : /* all new processes are childern of parent */
187 if ( (pid = fork()) == -1 ) {
188 if ( prefix != NULL )
189 fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
190 prefix, __FILE__, errno, strerror(errno));
196 case 0: /* child - stops the forking */
197 if ( Forker_npids < FORKER_MAX_PIDS )
198 Forker_pids[Forker_npids-1]=getpid();
201 default: /* parent - continues the forking */
202 if ( Forker_npids < FORKER_MAX_PIDS )
203 Forker_pids[Forker_npids-1]=pid;
210 if ( Forker_npids < FORKER_MAX_PIDS )
211 Forker_pids[Forker_npids]=0;
214 } /* end of forker */
220 * The following is a unit test main for the background and forker
235 printf("Usage: %s ncopies [mode]\n", argv[0]);
239 if ( sscanf(argv[1], "%i", &ncopies) != 1 ) {
240 printf("%s: ncopies argument must be integer\n", argv[0]);
245 if ( sscanf(argv[2], "%i", &mode) != 1 ) {
246 printf("%s: mode argument must be integer\n", argv[0]);
250 printf("Starting Pid = %d\n", getpid());
251 ret=background(argv[0]);
252 printf("After background() ret:%d, pid = %d\n", ret, getpid());
254 ret=forker(ncopies, mode, argv[0]);
256 printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n",
257 ncopies, mode, argv[0], ret, getpid());
259 printf("%d My version of Forker_pids[], Forker_npids = %d\n",
260 getpid(), Forker_npids);
262 for (ind=0; ind<Forker_npids; ind++){
263 printf("%d ind:%-2d pid:%d\n", getpid(), ind, Forker_pids[ind]);
270 #endif /* UNIT_TEST */