我在Linux中创build一个进程混淆。 到目前为止,我认为我们可以通过调用以下系统调用来创build进程。
system()
exec()
系列 fork()
系统调用 但:
system():但是作为执行shell和shell的input可执行文件的“system”系统调用正在为input的执行创build一个subprocess。这个shell正在调用subprocess,那么我们可以说fork正在为此创build进程。
系统调用的exec系列:由于这个系统调用系列将当前正在运行的进程写入新的进程,因此它也创build一个新的进程,但使用相同的地址空间。 因为我认为它也叫调用fork来创build进程。
我感到困惑的是,以上所有都是创build一个新stream程或者只有分叉系统的可能方式。
系统调用的exec
系列不会调用fork
,也不会创建一个新的进程。 它只用新的二进制覆盖现有的进程。
在linux
用户程序中, fork
是创建新进程的唯一函数。 虽然fork
内部调用clone
和其他系统调用。
另一方面, system
只是fork
和exec
的封装。 创建一个进程的实际任务是由fork
in system
完成的。 所以system
不是创建新进程的一种方式。
fork()
创建一个你的进程的副本。 这就是您在像Linux这样的POSIX环境中实际创建一个进程的地方。 要精确地回答您的问题标题, fork()
是创建流程的唯一方法。
那么exec()
为你做的是用另一个进程替换一个进程(例如你用fork()
创建的进程exec()
,所以exec()
本身并不创建一个进程,但通常伴随着fork()
因为你通常想要创建另一个与当前不同的进程。
在system()
调用下面,只有一个fork()
后跟一个exec()
,所以这不是创建一个进程的新方法。
在POSIX环境中,您可以通过fork
系统调用来创建一个进程,而无任何异常。 叉将创建一个过程。
exec
系列函数只是将其他程序的二进制文件加载到当前进程(调用exec()系统调用)的地址空间中。
在system()
它在内部使用fork()
后跟exec()
系统调用。
创建新进程只有两种方法:系统调用fork
和clone
。
其他提到的功能分为两类:
exec()
系列:用一些其他程序替换一个进程的内容。 通常,在调用fork
或clone
之后,会立即使用exec()
,将其中一个生成的进程转换为所需应用程序的进程。 例如,当一个bash
执行一个gcc
命令时,它首先分叉自身,然后它使用exec()
系列将两个由此产生的bash
过程中的一个转换为一个gcc
过程。
system()
系列:这些封装了一个fork
/ clone
系统调用和一个相应的exec()
调用,可能会像连接stdin
和stdout
一样花哨的东西。
请注意,所有这些函数fork()
, clone()
, exec()
, system()
等都是由标准C库(始终存在)定义的系统调用包装器,而不是系统调用自身。 因此,反直觉地说, fork()
是当前系统上clone
系统调用的包装。 不是那么重要。 但是,C库函数是标准化的,系统调用不是。
从历史上看, fork
是较老的系统调用。 虽然定义和使用其语义非常容易,但它总是会受到性能的影响:整个过程环境需要(至少在逻辑上)被复制,然而,大部分工作都是无用的,因为其中一个结果过程通常被exec
调用完全覆盖。 此外, fork
语义不允许创建线程。 由于这些缺点, clone
调用被引入,这允许对复制的内容进行细粒度的控制,以及两个进程之间共享的内容,从而允许以clone
方式实现pthreads
。
除了所有其他的答案,并挑剔,进程是由fork(2) (或过时的vfork(2) …)和clone(2)系统调用(和no, execve(2)系统调用创建一个进程,但是通过在同一进程中启动一个新程序来覆盖它的地址空间和状态),但是一些进程是由内核创建的“神奇”的,特别是:
/sbin/init
在启动时由内核启动(如果没有找到,则尝试其他程序,甚至是/bin/sh
….); 这是pid 1在很早就开始的过程…
一些内核进程(或内核线程)是由内核启动的,比如kswapd , kworker
(参见这个问题)等等。我有超过50个内核进程或任务
Linux内核有时也启动内核的用户进程,特别是hotplug(8) , modprobe等…另请参阅udev等…
几乎所有进程都由fork
(或clone
…)启动,并且是/sbin/init
(或者pid 1的进程)的后代。 (但modprobe
或hotplug
可以由内核启动,并且通常会fork
其他进程)。
过程创建(通过fork
等….)是相当有效的。 一个shell几乎可以分出所有的命令(除了内置的命令,比如cd
或者ulimit
)。 clone
是多线程所必需的(但可以用来替代fork
)
注意system(3) , popen(3)是库函数 (不是系统调用 ,在syscalls(2) …中列出)调用fork
和execve
(on /bin/sh
…),而守护进程3)是一个库函数调用fork
(两次)等…
使用strace(1) (找出哪个系统调用程序正在执行)并阅读高级Linux编程
现在,最近的Libc使用的clone
比fork
更多(有些不再调用fork
syscall,而只是clone
); 你可以有几个libc,例如MUSL libc (或者替代) GNU libc