fork()是否会创建别名?

时间:2016-09-20 01:01:08

标签: c linux operating-system fork

当我使用fork()创建子进程时,子进程与父进程重复。指针是指向每个进程中的相同内容还是指针在子进程中获取新值。数组或文件指针怎么样?

2 个答案:

答案 0 :(得分:3)

指针指向每个进程中的相同内容。

是的,所有内存都被复制,包括指针。

数组或文件指针怎么样?

是。对于文件 descriptors ,请注意在父进程中打开的任何文件描述符都将引用子进程中的相同文件。

大多数(全部?)Unix系统使用某种形式的写时复制优化,这意味着进程实际上将共享物理内存,直到它们中的任何一个写入内存。这往往会使fork()成为一种非常便宜的操作。

如Vazquez-Abrams所述,有一些极端案件。也许最重要的一个是只分叉一个线程,即调用fork()系统调用的线程。

答案 1 :(得分:0)

来自fork(2) man page(强调我的):

  

新流程(称为子流)是调用流程的完全重复,称为父,除了以下几点:

     

*       子进程具有自己唯一的进程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()的线程。父节点的整个虚拟地址空间在子节点中复制,包括互斥锁,条件变量和其他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上他们没有。