新进程,称为子进程,是调用进程(称为父进程)的完全相同,除了以下几点:: p>
*
子进程有自己唯一的进程 ID,并且这个 PID 不匹配任何现有进程组的 ID (setpgid(2))。
*
子进程的父进程 ID 与父进程 ID 相同。
*
子进程不会继承其父进程的内存锁(mlock(2)、mlockall(2))。
*
进程资源利用率 (getrusage(2)) 和 CPU 时间计数器 (times(2)) 在子进程中重置为零。
*
孩子的待处理信号集最初是空的(sigpending(2))。
*
子进程不会从其父进程 (semop(2)) 继承信号量调整。
*
子进程不会从其父进程 (fcntl(2)) 继承记录锁。
*
子进程不会从其父进程继承计时器(setitimer(2)、alarm(2)、timer_create(2))。
*
子进程不会从其父进程(aio_read(3)、aio_write(3))继承未完成的异步 I/O 操作,也不会从其父进程继承任何异步 I/O 上下文(请参阅 io_setup(2))。
上述列表中的进程属性均在 POSIX.1-2001 中指定。父子进程在以下 Linux 特定进程属性方面也有所不同:
*
子进程不会从其父进程继承目录更改通知 (dnotify)(参见 fcntl(2) 中对 F_NOTIFY 的描述)。
*
prctl(2) PR_SET_PDEATHSIG 设置被重置,以便子级在其父级终止时不会收到信号。
*
默认计时器松弛值设置为父级的当前计时器松弛值。请参阅 prctl(2) 中对 PR_SET_TIMERSLACK 的描述。
*
使用 madvise(2) MADV_DONTFORK 标志标记的内存映射不会通过 fork() 继承。
*
子进程的终止信号始终是 SIGCHLD(参见 clone(2))。
*
ioperm(2) 设置的端口访问权限位不被孩子继承;孩子必须使用 ioperm(2) 打开它需要的任何位。
请注意以下几点:
*
子进程是用一个线程创建的——即调用 fork() 的线程。父级的整个虚拟地址空间在子级中复制,包括互斥锁、条件变量和其他 pthread 对象的状态;使用 pthread_atfork(3) 可能有助于处理这可能导致的问题。
*
子继承父的一组打开文件描述符的副本。子文件中的每个文件描述符与父文件中的相应文件描述符引用相同的打开文件描述(请参阅 open(2))。这意味着两个描述符共享打开文件状态标志、当前文件偏移量和信号驱动的 I/O 属性(参见 fcntl(2) 中对 F_SETOWN 和 F_SETSIG 的描述)。
*
子进程继承父进程的一组开放消息队列描述符的副本(参见 mq_overview(7))。子项中的每个描述符都与父项中的相应描述符引用相同的打开消息队列描述。这意味着两个描述符共享相同的标志 (mq_flags)。
*
子进程继承父进程的一组开放目录流的副本(参见 opendir(3))。 POSIX.1-2001表示父子中对应的目录流可以共享目录流定位;在 Linux/glibc 上他们没有。