|
» |
|
|
|
| | |
Process 0 is created and initialized at system boot time but
all other processes are created by a fork()
or vfork() system call. The fork()
system call causes the creation of a new process. The new (child)
process is an exact copy of the calling (parent) process. vfork() differs
from fork() only in that the child
process can share code and data with the calling process (parent
process). This speeds cloning activity significantly at a risk to
the integrity of the parent process if vfork()
is misused.
| | | | | NOTE: The use of vfork()
for any purpose except as a prelude to an immediate exec()
or exit() is not supported. Any
program that relies upon the differences between fork()
and vfork() is not portable across
HP-UX systems. | | | | |
Table 1-4 Comparison
of fork() and vfork() fork() | vfork() |
---|
Sets context to point to parent.Child process
is an exact copy of the parent process. (See fork(2)
manpage for inherited attributes.) | Can share parent's data and code.
vfork() returns 0 in the child's
context and (later) the pid of the child in the parent's
context. | Copy on access | Child borrows the parent's memory
and thread of control until a call to exec()
or exit().Parent must sleep while
the child is using its resources, since child shares stack and
uarea | Must reserve swap | No reservation of swap |
When fork'd, the
child process inherits the following attributes from the parent
process: Real, effective, and saved user IDs. Real, effective, and saved group IDs. List of supplementary group IDs (see getgroups(2)). Close-on-exec flags (see exec(2)). Signal handling settings (SIG_DFL, SIG_IGN,
address). Signal mask (see sigvector(2)). Profiling on/off status (see profil(2)). Command name in the accounting record (see acct(4)). Nice value (see nice(2)). All attached shared memory segments (see shmop(2)). Current working directory Root directory (see chroot(2)). File mode creation mask (see umask(2)). File size limit (see ulimit(2)). Real-time priority (see rtprio(2)).
Each child file descriptor shares a common open file description
with the corresponding parent file descriptor. Thus, changes to
the file offset, file access mode, and file status flags of file
descriptors in the parent also affect those in the child, and vice-versa. The child process differs from the parent process in the following
ways: The child process has a unique process
ID. The child process has a different parent process
ID (which is the process ID of the parent process). The set of signals pending for the child process
is initialized to the empty set. The trace flag (see the ptrace(2) PT_SETTRC
request is cleared in the child process. The AFORK flag
in the ac_flags component of the accounting record is set in the
child process. Process locks, text locks, and data locks are not
inherited by the child (see plock(2)). All semadj values
are cleared (see semop(2)). The child process's values for tms_utime, tms_stime, tms_cutime, and tms_cstime are
set to zero.. The time left until an alarm clock signal is reset
to 0 (clearing any pending alarm), and all interval timers are set
to 0 (disabled).
The fork1() Routine | |
Both fork() and vfork()
call the fork1() routine to create
a new process, specifying as forktype: FORK_PROCESS
when the fork() system call is
used FORK_VFORK when
the vfork() system call is used
The next table itemizes the subroutines performed by fork1(). Table 1-5 fork1(forktype) Subroutine | Purpose |
---|
getnewpid() | Set up unique process ID. The following
PIDs are reserved for the system: | getnewtid() | Set up unique thread ID for the main
thread of the new process. The following TIDs are reserved for
the system: | proc_count() | Verify that a user process does not exceed
nproc (maximum number of proc
table entries) | allocproc() | Allocate space for the proc
structure entry and clear it. Allocate memory required
for the process by a call to kmalloc.
Remove the allocated process table slot from the free
list. Mark the entry "process creation in progress",
corresponding to a p_flag definition
of SIDL (process creation state). | allocthread() | Allocate space for the thread structure and
add it to the active thread list.Initialize the entry to a kthread
flag state of TSIDL (thread creation
state) | link_thread_to_proc() | Link the child thread structure to its proc
structure | thread_hash(), proc_hash() | Hash the child thread structure for its TID
and the proc structure for its
UID and PID. | | Link the child thread structure to the active
threads list and the child process to the active process list |
If fork1() is called with
a forktype of FORK_VFORK,
memory is allocated and initialized for a
vforkinfo() structure, which is
referenced through the proc structures
of the parent/child vfork() pair.
The vforkinfo structure holds
state information about the vfork()
and a copy of the parent stack. The vforkinfo()
structure is used throughout process creation while the child decides
to exit() or exec().
struct vforkinfo is found in proc_private.h. fork1() switches to newproc(),
giving it forktype, proc table
slot, and thread with which to create the new process. The newproc() Routine | |
When fork1 calls newproc(),
things proceed differently depending on whether forktype
is FORK_VFORK or FORK_PROCESS. newproc() gets a pointer
to the parent process and ascertains that no other forks
or exits are occurring at the same
time. newproc()
verifies the kt_stat (thread state)
is TSIDL; if not it panics. newproc() gets
a pointer to the parent process and thread. When called by vfork,
newproc() allocates the vforkinfo
buffer, by calling vfork_buffer_init() vfork_buffer_init()
determines the kernel stack size, uarea size, and room for growth,
allocates memory, fills in vforkbuf
information, saves frame_size,
pointer to parent's uarea,
and pointer to last buffer.
newproc() computes
the size of the fork, then acquires
the sched_lock. While holding the lock, newproc()
updates process statistics. newproc() calls
dbfork() subroutine to set up the
child's flags to adhere to locking rules (documented in
proc_private.h). The child process
p_flag is set to SLOAD
and the child thread kt_flag is
set to TSFIRSTTHREAD. newproc() calls
reload_ticksleft() to update the
child thread (ct) and mark the
parent proc pointer (pp)
unswappable by calling make_unswappable().
This is to prevent to parent from being swapped while the environment
is copied for the child. newproc() releases
the spinlock, determines whether the parent is a graphics process
(if so, sets up the child save state), simulates the environment
of the new process, prevents the parent from being swapped, then
switches to procdup(), providing
it forktype and addresses of parent
and child process and thread.
If newproc() is called by
fork1(FORK_PROCESS), newproc()
creates the new child process by calling makechild(). newproc()
calls make_unswappable() to prevent
the parent from being swapped. newproc() switches
to procdup(), passing it forktype
and addresses of parent and child process and thread.
The procdup() Routine | |
newproc() calls procdup() when most of the child's
structure has been created, passing to it the forktype, parent's
proc pointer (pp), child's proc pointer (cp), parent's
thread (pt), and child's thread (ct). As it executes, procdup()
does the following: Builds a uarea
and address space for the child. Duplicates the parent's virtual address
space. Creates a new region for the child's uarea. Attaches the region: PF_NOPAGE
keeps vhand from paging the uarea. Marks the pregion to be owned by new child process.
The address space is owned by the process. Places the child thread on the run queue by calling
setrq(). The child thread is
marked SET_RUNRUN and the thread
is unlocked.
vfork State information
in struct vforkinfoTo prepare a vfork'd
process to run, the vfork_state
is maintained in struct vforkinfo.
Five states are defined: During the fork1() routine,
vfork_buffer_init sets the vfork_state
in vforkinfo to VFORK_INIT.
When procdup() places the child
thread on the run queue by calling setrq(),
it also sets the vfork_state to VFORK_PARENT.
The parent sleeps and is not awakened until the child exits
or execs. At this point the parent
and child share the same uarea
and stack. If the process was initiated with fork()
rather than vfork(), the spinlock
is unlocked and the process is made swappable. The child process runs using the parent's stack until
it does an exec() or exit().
|