fork()
Create a new process
Synopsis:
#include <sys/types.h>
#include <unistd.h>
pid_t fork( void );
This function is declared in <process.h>, which <unistd.h> includes.
Library:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
Description:
- The child process has a unique process ID.
- The child process has a different parent process ID (which is the process ID of the calling process).
- The child process has its own copy of the parent's file descriptors. Each of the child's file descriptors refers to the same open file description with the corresponding file descriptor of the parent.
- The child process has its own copy of the parent's open directory streams.
- The child process's values of tms_utime, tms_stime, tms_cutime, and tms_cstime are set to zero.
- The child process has a single thread, regardless of the number that the parent has.
- File locks previously set by the parent aren't inherited by the child.
- The child process doesn't inherit any timers, QNX OS message-passing objects, side-channel connection IDs (coids), or channels (chids).
- The child process doesn't inherit I/O privileges.
- The set of signals pending for the child process is initialized to the empty set.
- No event notification requests, such as those requested with ionotify(), mq_notify(), procmgr_event_notify(), or procmgr_value_notify(), are inherited by the child.
- No events attached to interrupt sources through InterruptAttachEvent() or InterruptAttachEventPriority() are inherited by the child.
- A named semaphore (sem_open()) increments and decrements the same count in the parent and child, but an unnamed semaphore (sem_init()) increments and decrements a different count (with the same initial value) in the two processes, unless that semaphore is in a shared memory object.
- The child inherits any message queue descriptors from the parent.
- The child inherits any memory mappings that were created in the parent, except for those that
have the MAP_NOINHERIT flag set (see mmap()).
MAP_PRIVATE mappings inherited from the parent are also MAP_PRIVATE mappings in the child, and any modifications to the data in these mappings made by the parent prior to calling fork() are visible to the child. Any modifications to the data in MAP_PRIVATE mappings made by the parent or child after a fork() are visible only to the parent or child, respectively.
- The parent's ability configuration (see procmgr_ability()) is copied to the child verbatim, regardless of the PROCMGR_AOP_INHERIT_NO status of each of the abilities.
- If the parent is a resource manager, then the child can't be a resource manager until after an exec().
- If the parent has used any of the aio_*() functions, then the child can't use any of the aio_*() functions until after an exec().
- If the child will link a library at load time or at run time (i.e., with dlopen()), the child must be given the PROCMGR_AID_PROT_EXEC and PROCMGR_AID_MAP_FIXED abilities. For more information, see procmgr_ability().
In order to successfully call this function, your process must have the PROCMGR_AID_FORK ability enabled. For more information, see procmgr_ability().
You can use pthread_atfork() to register fork handler functions to be called before or after the fork occurs.
- POSIX requires that the child process use only functions that are async-signal-safe until it calls one of the exec*() functions. If your program uses mutexes, you might need to use a forksafe mutex or register a pthread_atfork() handler that locks all the mutexes before you fork.
- A thread must not hold a forksafe_mutex_t when it invokes fork(), or else a deadlock will occur. The same is true of a pthread_mutex_t that's protected by an at-fork handler.
For more information, see
Using fork() in a multithreaded process
in the Processes and Threads
chapter of Getting Started with the QNX OS.
Returns:
A value of zero to the child process, and the process ID of the child process to the parent process. Both processes continue to execute from the fork() function. If an error occurs, fork() returns -1 to the parent and sets errno.
Errors:
- EAGAIN
- Insufficient resources are available to create the child process. For example, you might have exceeded the maximum number of processes permitted; see the RLIMIT_NPROC resource for getrlimit().
- EBADF
- A problem occurred when fork() was duplicating a file descriptor. For example, another thread might have opened or closed a file descriptor while the fork() was occurring. You can add synchronization around the operations that involve file descriptors, or try calling fork() again.
- ENOMEM
- The process requires more memory than the system is able to supply.
- ENOSYS
- The fork() function isn't implemented for this memory protection model.
- EPERM
- One of the following occurred:
- The calling process doesn't have the required permission; see procmgr_ability().
- The calling process's priority is above the permitted range.
- ENXIO
- The process has a shared mapping (MAP_SHARED) of a shared memory object and the object has been reduced in size such that one or more pages of the mapping are no longer within the object (e.g., by an ftruncate() to a smaller size after mapping the original size).
Examples:
This program demonstrates forking. You run it like this:
fork_example program [arguments]
The child runs program (passing it the arguments, if any), and the parent waits for the child to exit.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main( int argc, char **argv )
{
pid_t pid;
pid_t wpid;
int status;
if (argc == 1) {
printf ("Usage: %s <program> [<arguments>]\n", argv[0]);
return EXIT_FAILURE;
}
if( ( pid = fork() ) == -1 ) {
perror( "fork" );
return EXIT_FAILURE;
}
if( pid == 0 ) {
printf ("Child: My pid is %d.\n", getpid() );
/* Use exec to become the specified program. */
execvp( argv[1], argv+1 );
/* This can happen only if execvp() fails; print a message, and then exit. */
perror( argv[1] );
return EXIT_FAILURE;
} else {
printf ("Parent: My pid is %d.\n", getpid() );
/* Wait for the child to finish. */
do {
wpid = waitpid( pid, &status, 0 );
} while( WIFEXITED( status ) == 0 );
printf ("Parent: Child %d has exited with status %d; we're done!\n",
wpid, WEXITSTATUS( status ));
return WEXITSTATUS( status );
}
}
Classification:
Safety: | |
---|---|
Cancellation point | No |
Signal handler | Yes |
Thread | Read the Caveats |
Caveats
It's possible to call fork() from a multithreaded process, but it can be very difficult
to do so safely, so we recommend that you call it only from single-threaded processes.
For more information, see
Using fork() in a multithreaded process
in the Processes and Threads
chapter of Getting Started with the QNX OS.