fork() — Create a new process
Standards
Standards / Extensions | C or C++ | Dependencies |
---|---|---|
POSIX.1
XPG4 XPG4.2 Single UNIX Specification, Version 3 |
both |
Format
#define _POSIX_SOURCE
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
General description
- The child process has a unique process ID (PID) that does not match any active process group ID.
- The child has a different parent process ID, that is, the process ID of the process that called fork().
- The child has its own copy of the parent's file descriptors. Each file descriptor in the child refers to the same open file description as the corresponding file descriptor in the parent.
- The child has its own copy of the parent's open directory streams. Each child's open directory stream can share directory stream positioning with the corresponding parent's directory stream.
- The following elements in the
tms
structure are set to 0 in the child:tms_utime
tms_stime
tms_cutime
tms_cstime
For more information about these elements, see times() — Get process and child process times.
- The child does not inherit any file locks previously set by the parent.
- The child process has no alarms set (similar to the results of a call to alarm() with an argument value of 0).
- The child has no pending signals.
- The child process has only a single thread. That thread is a copy of the thread in the parent that called fork(). The child process has a different thread ID. If the parent process was multithreaded (invoked pthread_create() at least once), the child process can only safely invoke async-signal-safe functions before it invokes an exec() family function. (This restriction also applies to any process created as the result of the child invoking fork() before it invokes an exec() family function because the child process is still considered multithreaded.) The child process does not inherit pthread attributes or pthread security environment. See Table 1 for a list of async-signal-safe functions.
In all other respects, the child is identical to the parent. Because the child is a duplicate, it contains the same call to fork() that was in the parent. Execution begins with this fork() call, which returns a value of 0; the child then proceeds with normal execution.
- Region size
- Time limit
If the parent process is multithreaded, it is the responsibility of the application to ensure that the application data is in a consistent state when the fork() occurs. For example, mutexes that are used to serialize updates to application data may need to be locked before the fork() and unlocked afterwards.
For more information on fork(), refer to z/OS UNIX System Services Programming: Assembler Callable Services Reference.
You can use MVS™ memory files from a z/OS® UNIX program. However, use of the fork() function from the program removes access from a hiperspace memory file for the child process. Use of an exec function from the program clears a memory file when the process address space is cleared.
The child process that results from a fork() in a multithreaded environment can only invoke async-signal-safe functions.
An async-signal-safe function is defined as a function that may be invoked, without restriction, from signal-catching functions. All supported async-signal-safe functions are listed in Table 1.
abort() | fpathconf() | raise() | sigpending() |
accept() | fstat() | read() | sigprocmask() |
access() | fsync() | readlink() | sigqueue() |
aio_error() | ftruncate() | recv() | sigset() |
aio_return() | getegid() | recvfrom() | sigsuspend() |
aio_suspend() | geteuid() | recvmsg() | socket() |
alarm() | getgid() | rename() | socketpair() |
bind() | getgroups() | rmdir() | stat() |
cfgetispeed() | getpeername() | select() | symlink() |
cfgetospeed() | getpgrp() | send() | sysconf() |
cfsetispeed() | getpid() | sendmsg() | tcdrain() |
cfsetospeed() | getppid() | sendto() | tcflow() |
chdir() | getsockname() | setgid() | tcflush() |
chmod() | getsockopt() | setpgid() | tcgetattr() |
chown() | getuid() | setsid() | tcgetpgrp() |
close() | kill() | setsockopt() | tcsendbreak() |
connect() | link() | setuid() | tcsetattr() |
creat() | listen() | shutdown() | tcsetpgrp() |
dup() | lseek() | sigaction() | time() |
dup2() | lstat() | sigaddset() | times() |
execle() | mkdir() | sigdelset() | umask() |
execve() | mkfifo() | sigemptyset() | uname() |
_Exit() | open() | sigfillset() | unlink() |
_exit() | pathconf() | sigismember() | utime() |
fchmod() | pause() | sleep() | wait() |
fchown() | pipe() | signal() | waitpid() |
fcntl() | poll() | sigpause() | write() |
fork() |
Interoperability restriction: For POSIX resources, fork() behaves as just described. But in general, MVS resources that existed in the parent do not exist in the child. This is true for open streams in MVS data sets and assembler-accessed MVS facilities, such as STIMERS. In addition, MVS allocations (through JCL, SVC99, or ALLOCATE) are not passed to the child process.
- A prior loaded copy of an HFS program in the same address space
is reused under the same circumstances that apply to the reuse of
a prior loaded MVS unauthorized
program from an unauthorized library by the MVS XCTL service with the following exceptions:
- If the calling process is in Ptrace debug mode, a prior loaded copy is not reused.
- If the calling process is not in Ptrace debug mode, but the only prior loaded usable copy found of the HFS program is in storage modifiable by the caller, the prior copy is not reused.
- If the specified file name represents an external link or a sticky bit file, the program is loaded from the caller's MVS load library search order. For an external link, the external name is only used if the name is eight characters or less, otherwise the caller receives an error from the loadhfs service. For a sticky bit program, the file name is used if it is eight characters or less. Otherwise, the program is loaded from the HFS.
- If the calling task is in a WLM enclave, the resulting task in the new process image is joined to the same WLM enclave. This allows WLM to manage the old and new process images as one ‘business unit of work’ entity for system accounting and management purposes.
Returned value
If successful, fork() returns 0 to the child process and the process ID of the newly created child to the parent process.
- Error Code
- Description
- EAGAIN
- There are insufficient resources to create another process, or the process has already reached the maximum number of processes you can run.
- ELEMSGERR
- Language Environment® message file not available.
- ELEMULTITHREAD
- Application contains a language that does not support fork() in a multithreaded environment, or the multithreaded fork() is being attempted while running in a Language Environment preinitialization (CEEPIPI) environment.
- ELENOFORK
- Application contains a language that does not support fork().
- ENOMEM
- The process requires more space than is available.
Example
/* CELEBF27
This example creates a new child process.
*/
#define _POSIX_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
main() {
pid_t pid;
int status;
if ((pid = fork()) < 0)
perror("fork() error");
else if (pid == 0) {
puts("This is the child.");
printf("Child's pid is %d and my parent's is %d\n",
(int) getpid(), (int) getppid());
exit(42);
}
else {
puts("This is the parent.");
printf("Parent's pid is %d and my child's is %d\n",
(int) getpid(), (int) pid);
puts("I'm waiting for my child to complete.");
if (wait(&status) == -1)
perror("wait() error");
else if (WIFEXITED(status))
printf("The child exited with status of %d\n",
WEXITSTATUS(status));
else
puts("The child did not exit successfully");
}
}
This is the parent.
This is the child.
Child's pid is 1114120 and my parent's is 2293766
Parent's pid is 2293766 and my child's is 1114120
I'm waiting for my child to complete.
The child exited with status of 42
Related information
- sys/types.h — typedef symbols and structures
- unistd.h — Implementation-specific functions
- alarm() — Set an alarm
- exec functions
- fcntl() — Control open file descriptors
- getrlimit() — Get current or maximum resource consumption
- kill() — Send a signal to a process
- nice() — Change priority of a process
- putenv() — Change or add an environment variable
- semop() — Semaphore operations
- shmat() — Shared memory attach operation
- sysconf() — Determine system configuration options
- times() — Get process and child process times
- ulimit() — Get or set process file size limits
- wait() — Wait for a child process to end