FORK - Linux手册页

时间:2019-08-20 17:58:43  来源:igfitidea点击:

Linux程序员手册 第2部分
更新日期: 2020-06-09

名称

fork-创建一个子进程

语法

#包括
#包括

pid_t fork(无效);

说明

fork()通过复制调用过程来创建一个新过程。新进程称为子进程。调用过程称为父进程。

子进程和父进程在单独的内存空间中运行。在fork()时,两个内存空间具有相同的内容。其中一个进程执行的内存写入,文件映射(mmap(2))和取消映射(munmap(2))不会影响另一个进程。

子进程与父进程完全相同,但以下几点除外:

*
子进程具有其自己的唯一进程ID,并且此PID与任何现有进程组(setpgid(2))或会话的ID不匹配。
*
子级的父进程ID与父级的进程ID相同。
*
子代不会继承其父代的内存锁(mlock(2),mlockall(2))。
*
子进程中的进程资源利用率(getrusage(2))和CPU时间计数器(times(2))被重置为零。
*
孩子的未决信号集最初是空的(sigpending(2))。
*
子级不会从其父级继承信号量调整(semop(2))。
*
子级不会从其父级(fcntl(2))继承与进程相关的记录锁。 (另一方面,它确实从其父项继承了fcntl(2)打开文件描述锁和flock(2)锁。)
*
子级不会从其父级(setitimer(2),alarm(2),timer_create(2))继承计时器。
*
子级不会从其父级(aio_read(3),aio_write(3))继承未完成的异步I / O操作,也不会从其父级继承任何异步I / O上下文(请参见io_setup(2))。

上面列表中的过程属性都在POSIX.1中指定。父级和子级在以下特定于Linux的进程属性方面也有所不同:

*
子级不会从其父级继承目录更改通知(通知)(请参阅fcntl(2)中对F_NOTIFY的描述)。
*
重置prctl(2)PR_SET_PDEATHSIG设置,以使子级在其父级终止时不接收信号。
*
默认计时器松弛值设置为父级的当前计时器松弛值。请参阅prctl(2)中对PR_SET_TIMERSLACK的描述。
*
带有madvise(2)MADV_DONTFORK标志标记的内存映射不会在fork()上继承。
*
fork()之后,子级中已用madvise(2)MADV_WIPEONFORK标志标记的地址范围内的内存为零。 (对于子级中的那些地址范围,MADV_WIPEONFORK设置保持不变。)
*
子项的终止信号始终为SIGCHLD(请参见clone(2))。
*
ioperm(2)设置的端口访问许可位不会被子级继承;子级必须使用ioperm(2)打开所需的任何位。

请注意以下几点:

*
子进程由一个线程创建,该线程称为fork()。父级的整个虚拟地址空间都在子级中复制,包括互斥体的状态,条件变量和其他pthreads对象;使用pthread_atfork(3)可能有助于解决可能引起的问题。
*
在多线程程序中执行fork()之后,子级只能安全地调用异步信号安全函数(请参见signal-safety(7)),直到调用execve(2)为止。
*
子级继承父级打开文件描述符集的副本。子级中的每个文件描述符都与父级中的相应文件描述符引用相同的打开文件描述(请参阅open(2))。这意味着这两个文件描述符共享打开的文件状态标志,文件偏移和信号驱动的I / O属性(请参阅fcntl(2)中对F_SETOWN和F_SETSIG的描述)。
*
子级继承父级的开放消息队列描述符集的副本(请参阅mq_overview(7))。子级中的每个文件描述符都与父级中的相应文件描述符引用相同的打开消息队列描述。这意味着两个文件描述符共享相同的标志(mq_flags)。
*
子级继承父级的一组打开目录流的副本(请参见opendir(3))。 POSIX.1说父级和子级中的相应目录流可以共享目录流的位置;在Linux / glibc上却没有。

返回值

成功后,将在父级中返回子进程的PID,在子级中返回0。如果失败,则在父级中返回-1,不创建任何子级进程,并正确设置errno。

错误说明

EAGAIN

A system-imposed limit on the number of threads was encountered.
There are a number of limits that may trigger this error:

*
达到了RLIMIT_NPROC软资源限制(通过setrlimit(2)设置),该限制限制了实际用户ID的进程和线程数;
*
达到了内核在系统范围内对进程和线程数的限制,即/ proc / sys / kernel / threads-max(请参见proc(5));
*
PID的最大数量已达到/ proc / sys / kernel / pid_max(请参见proc(5));要么
*
达到了cgroup"进程号"(PIDs)控制器施加的PID限制(pids.max)。
EAGAIN
调用方正在根据SCHED_DEADLINE调度策略进行操作,并且未设置"分叉重置"标志。参见sched(7)。
ENOMEM
由于内存紧张,fork()无法分配必要的内核结构。
ENOMEM
试图在其" init"进程已终止的PID名称空间中创建子进程。参见pid_namespaces(7)。
ENOSYS
此平台不支持fork()(例如,没有内存管理单元的硬件)。
ERESTARTNOINTR(since Linux 2.6.17)
系统调用已被信号中断,将重新启动。 (这只能在跟踪期间看到。)

遵循规范

POSIX.1-2001,POSIX.1-2008,SVr4、4.3BSD。

备注

在Linux下,fork()是使用写时复制页面实现的,因此它唯一的代价就是复制父级的页表并为子级创建唯一的任务结构所需的时间和内存。

C library/kernel differences

从2.3.3版开始,作为NPTL线程实现的一部分提供的glibc fork()包装器而不是调用内核的fork()系统调用,而是使用带有与传统系统调用相同的效果的标志来调用clone(2)。 。 (对fork()的调用等效于对将标志指定为SIGCHLD的clone(2)的调用。)glibc包装器将调用使用pthread_atfork(3)建立的所有fork处理程序。

示例

参见pipe(2)和wait(2)。

另外参见

clone(2),execve(2),exit(2),setrlimit(2),unshare(2),vfork(2),wait(2),daemon(3),pthread_atfork(3),capabilities(7),证书(7)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/