当我使用fork()
创buildsubprocess时,subprocess是父进程的重复进程。 指针指向每个进程中的同一个事物,还是指针在subprocess中有一个新的值。 那么数组或文件指针呢?
指针指向每个进程中的相同的东西吗?
是的,所有内存都被复制,包括指针。
那么数组或文件指针呢?
是。 在文件描述符的情况下,注意在父进程中打开的任何文件描述符都会引用子进程中的相同文件。
大多数(所有)Unix系统使用某种形式的写入时复制优化,这意味着这些进程实际上将共享物理内存,直到其中任何一个写入内存为止。 这往往使叉()一个相当便宜的操作。
巴斯克斯 – 艾布拉姆斯(Vazquez-Abrams)指出,有一些角落案件。 也许最重要的是只有一个线程分叉,即调用fork()系统调用的线程。
从fork(2)
手册页 (重点是我的):
被称为孩子的新过程与调用过程(称为父辈) 完全相同 , 除了以下几点 :
*孩子有自己独特的进程ID,并且这个PID不匹配任何现有进程组(setpgid(2))的ID。
*孩子的父进程ID与父进程ID相同。
*孩子不会继承父母的记忆锁(mlock(2),mlockall(2))。
*子进程资源利用率(getrusage(2))和CPU时间计数器(次数(2))重置为零。
*孩子的待决信号集合最初是空的(sigpending(2))。
*孩子不会从其父母继承信号量调整(semop(2))。
*孩子不从父母继承记录锁(fcntl(2))。
*孩子不从父母(setitimer(2),alarm(2),timer_create(2))继承定时器。
*孩子不从其父(aio_read(3),aio_write(3))继承未完成的异步I / O操作,也不从其父(见io_setup(2))继承任何异步I / O上下文。
前面列表中的进程属性全部在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(参见克隆(2))。
*由ioperm(2)设置的端口访问权限位不会被孩子继承; 孩子必须使用ioperm打开它需要的任何位(2)。
请注意以下几点:
*子进程是用一个线程创建的 – 一个叫做fork()的线程。 父项的整个虚拟地址空间被复制到子项中,包括互斥锁,条件变量和其他pthreads对象的状态; 使用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上他们没有。