1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000 Silicon Graphics, Inc.
6 /**************************************************************
8 * OS Testing - Silicon Graphics, Inc.
10 * FUNCTION NAME : forker
13 * FUNCTION TITLE : fork desired number of copies of the current process
14 * fork a process and return control to caller
17 * int forker(ncopies, mode, prefix)
22 * int background(prefix);
25 * extern int Forker_pids[];
26 * extern int Forker_npids;
28 * AUTHOR : Richard Logan
30 * CO-PILOT(s) : Dean Roehrich
32 * INITIAL RELEASE : UNICOS 8.0
35 * The background function will do a fork of the current process.
36 * The parent process will then exit, thus orphaning the
37 * child process. Doing this will not nice the child process
38 * like executing a cmd in the background using "&" from the shell.
39 * If the fork fails and prefix is not NULL, a error message is printed
40 * to stderr and the process will exit with a value of errno.
42 * The forker function will fork <ncopies> minus one copies
43 * of the current process. There are two modes in how the forks
44 * will be done. Mode 0 (default) will have all new processes
45 * be childern of the parent process. Using Mode 1,
46 * the parent process will have one child and that child will
47 * fork the next process, if necessary, and on and on.
48 * The forker function will return the number of successful
49 * forks. This value will be different for the parent and each child.
50 * Using mode 0, the parent will get the total number of successful
51 * forks. Using mode 1, the newest child will get the total number
52 * of forks. The parent will get a return value of 1.
54 * The forker function also updates the global variables
55 * Forker_pids[] and Forker_npids. The Forker_pids array will
56 * be updated to contain the pid of each new process. The
57 * Forker_npids variable contains the number of entries
58 * in Forker_pids. Note, not all processes will have
59 * access to all pids via Forker_pids. If using mode 0, only the
60 * parent process and the last process will have all information.
61 * If using mode 1, only the last child process will have all information.
63 * If the prefix parameter is not NULL and the fork system call fails,
64 * a error message will be printed to stderr. The error message
65 * the be preceeded with prefix string. If prefix is NULL,
66 * no error message is printed.
68 * SPECIAL REQUIREMENTS
72 * This should contain the description, author, and date of any
73 * "interesting" modifications (i.e. info should helpful in
74 * maintaining/enhancing this module).
75 * username description
76 * ----------------------------------------------------------------
77 * rrl This functions will first written during
78 * the SFS testing days, 1993.
81 * The child pids are stored in the fixed array, Forker_pids.
82 * The array only has space for 4098 pids. Only the first
83 * 4098 pids will be stored in the array.
85 **************************************************************/
89 #include <unistd.h> /* fork, getpid, sleep */
91 #include <stdlib.h> /* exit */
94 int Forker_pids[FORKER_MAX_PIDS]; /* holds pids of forked processes */
95 int Forker_npids=0; /* number of entries in Forker_pids */
97 /***********************************************************************
99 * This function will fork and the parent will exit zero and
100 * the child will return. This will orphan the returning process
101 * putting it in the background.
104 * 0 : if fork did not fail
105 * !0 : if fork failed, the return value will be the errno.
106 ***********************************************************************/
113 if ( prefix != NULL )
114 fprintf(stderr, "%s: In %s background(), fork() failed, errno:%d %s\n",
115 prefix, __FILE__, errno, strerror(errno));
118 case 0: /* child process */
127 } /* end of background */
129 /***********************************************************************
130 * Forker will fork ncopies-1 copies of self.
132 ***********************************************************************/
134 forker(ncopies, mode, prefix)
136 int mode; /* 0 - all childern of parent, 1 - only 1 direct child */
137 char *prefix; /* if ! NULL, an message will be printed to stderr */
138 /* if fork fails. The prefix (program name) will */
139 /* preceed the message */
147 for ( cnt=1; cnt < ncopies; cnt++ ) {
150 case 1 : /* only 1 direct child */
151 if ( (pid = fork()) == -1 ) {
152 if ( prefix != NULL )
153 fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
154 prefix, __FILE__, errno, strerror(errno));
160 case 0: /* child - continues the forking */
162 if ( Forker_npids < FORKER_MAX_PIDS )
163 Forker_pids[Forker_npids-1]=getpid();
166 default: /* parent - stop the forking */
167 if ( Forker_npids < FORKER_MAX_PIDS )
168 Forker_pids[Forker_npids-1]=pid;
174 default : /* all new processes are childern of parent */
175 if ( (pid = fork()) == -1 ) {
176 if ( prefix != NULL )
177 fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
178 prefix, __FILE__, errno, strerror(errno));
184 case 0: /* child - stops the forking */
185 if ( Forker_npids < FORKER_MAX_PIDS )
186 Forker_pids[Forker_npids-1]=getpid();
189 default: /* parent - continues the forking */
190 if ( Forker_npids < FORKER_MAX_PIDS )
191 Forker_pids[Forker_npids-1]=pid;
198 if ( Forker_npids < FORKER_MAX_PIDS )
199 Forker_pids[Forker_npids]=0;
202 } /* end of forker */
208 * The following is a unit test main for the background and forker
223 printf("Usage: %s ncopies [mode]\n", argv[0]);
227 if ( sscanf(argv[1], "%i", &ncopies) != 1 ) {
228 printf("%s: ncopies argument must be integer\n", argv[0]);
233 if ( sscanf(argv[2], "%i", &mode) != 1 ) {
234 printf("%s: mode argument must be integer\n", argv[0]);
238 printf("Starting Pid = %d\n", getpid());
239 ret=background(argv[0]);
240 printf("After background() ret:%d, pid = %d\n", ret, getpid());
242 ret=forker(ncopies, mode, argv[0]);
244 printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n",
245 ncopies, mode, argv[0], ret, getpid());
247 printf("%d My version of Forker_pids[], Forker_npids = %d\n",
248 getpid(), Forker_npids);
250 for (ind=0; ind<Forker_npids; ind++){
251 printf("%d ind:%-2d pid:%d\n", getpid(), ind, Forker_pids[ind]);
258 #endif /* UNIT_TEST */