我对C来说是全新的。
使用fork();
创建的子项中继承的进程项有哪些?
与流程的父级不同的流程项是什么?
答案 0 :(得分:15)
这与C没什么关系,而是与fork()
有关,这是一个POSIX系统调用(我猜它在不同系统上的表现可能不同)。
我建议你阅读fork
manual,这是非常明确的:
fork()
通过复制调用进程来创建新进程。该 新的被称为孩子,是一个完全重复的呼叫 过程,称为父进程,但以下几点除外:
子项具有自己唯一的进程ID,并且此PID与任何现有进程组(
setpgid
(2))的ID不匹配。子进程的父进程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
设置已重置,以便子节点在其父节点终止时不会收到信号。标有
madvise
(2)MADV_DONTFORK
标记的内存映射不会在fork()
中继承。孩子的终止信号始终为
SIGCHLD
(请参阅clone
(2))。请注意以下几点:
使用单个线程创建子进程 - 调用
fork()
的线程。父级的整个虚拟地址空间是 复制在孩子身上,包括互斥状态,状况 变量和其他pthreads对象;使用pthread_atfork
(3) 可能有助于解决这可能导致的问题。子进程继承了父进程打开文件描述符的副本。子中的每个文件描述符都指向相同的open 文件描述(参见
open
(2))作为相应的文件描述符 在父母。这意味着两个描述符共享打开文件 状态标志,当前文件偏移和信号驱动的I / O属性 (请参阅F_SETOWN
(2)中F_SETSIG
和fcntl
的说明。子项继承了父组的开放消息队列描述符的副本(请参阅
mq_overview
(7))。孩子中的每个描述符 指的是与对应的相同的开放消息队列描述 父级中的描述符。这意味着两个描述符共享 相同的旗帜(mq_flags
)。子进程继承了父进程打开目录流的副本(参见
opendir
(3))。 POSIX.1-2001表示相应的 父级和子级中的目录流可以共享该目录 流定位;在Linux / glibc上他们没有。
如果您对Linux感兴趣,还应该检查clone
系统调用,以便更准确地指定您想要的内容。
答案 1 :(得分:5)
系统上的fork(2)手册页(man fork
)应该为您提供更好的细节,但通常孩子只会继承父文件描述符列表,包括打开文件,套接字和进程句柄。
从我系统的手册页(Mac OS X 10.6.6):
子进程有自己父级描述符的副本。 这些描述符引用相同的底层对象,因此 例如,文件对象中的文件指针是共享的 在孩子和父母之间,使一个lseek(2) 子进程中的描述符可能会影响后续的读取或 由父母写。此描述符复制也被使用 shell为新创建标准输入和输出 处理过程以及设置管道。
答案 2 :(得分:2)
答案 3 :(得分:1)
C中没有面向对象的继承。
C中的fork基本上是在它运行时被停止的进程,并且它的整个副本(有效地)在不同的内存空间中进行,然后两个进程被告知继续。他们将继续从父母暂停的地方继续。您可以判断自己所处的流程的唯一方法是检查fork()
来电的返回值。
在这种情况下,孩子并没有真正继承父母过程中的所有内容,更像是获得父母所拥有的所有内容的完整副本。
答案 4 :(得分:0)
与父母不同的孩子唯一的事情是
PPID即父进程ID 和
PID流程ID 。
当涉及到相似性时,子进程继承其父级的FILE DESCRIPTOR表,因此您会看到总是占用三个子级的FILE DESCRIPTORS,它们对应于 STDIN,STDOUT和STDERR 。