有多less种方法可以在linux下用c创build一个进程

我在Linux中创build一个进程混淆。 到目前为止,我认为我们可以通过调用以下系统调用来创build进程。

  1. system()
  2. 系统调用的exec()系列
  3. fork()系统调用

但:

  1. system():但是作为执行shell和shell的input可执行文件的“system”系统调用正在为input的执行创build一个subprocess。这个shell正在调用subprocess,那么我们可以说fork正在为此创build进程。

  2. 系统调用的exec系列:由于这个系统调用系列将当前正在运行的进程写入新的进程,因此它也创build一个新的进程,但使用相同的地址空间。 因为我认为它也叫调用fork来创build进程。

我感到困惑的是,以上所有都是创build一个新stream程或者只有分叉系统的可能方式。

系统调用的exec系列不会调用fork ,也不会创建一个新的进程。 它只用新的二进制覆盖现有的进程。

linux用户程序中, fork是创建新进程的唯一函数。 虽然fork内部调用clone和其他系统调用。

另一方面, system只是forkexec的封装。 创建一个进程的实际任务是由fork in system完成的。 所以system不是创建新进程的一种方式。

fork()创建一个你的进程的副本。 这就是您在像Linux这样的POSIX环境中实际创建一个进程的地方。 要精确地回答您的问题标题, fork()是创建流程的唯一方法。

那么exec()为你做的是用另一个进程替换一个进程(例如你用fork()创建的进程exec() ,所以exec()本身并不创建一个进程,但通常伴随着fork()因为你通常想要创建另一个与当前不同的进程。

system()调用下面,只有一个fork()后跟一个exec() ,所以这不是创建一个进程的新方法。

在POSIX环境中,您可以通过fork系统调用来创建一个进程,而无任何异常。 叉将创建一个过程。

exec系列函数只是将其他程序的二进制文件加载到当前进程(调用exec()系统调用)的地址空间中。

system()它在内部使用fork()后跟exec()系统调用。

创建新进程只有两种方法:系统调用forkclone

其他提到的功能分为两类:

  1. exec()系列:用一些其他程序替换一个进程的内容。 通常,在调用forkclone之后,会立即使用exec() ,将其中一个生成的进程转换为所需应用程序的进程。 例如,当一个bash执行一个gcc命令时,它首先分叉自身,然后它使用exec()系列将两个由此产生的bash过程中的一个转换为一个gcc过程。

  2. system()系列:这些封装了一个fork / clone系统调用和一个相应的exec()调用,可能会像连接stdinstdout一样花哨的东西。

请注意,所有这些函数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的进程)的后代。 (但modprobehotplug可以由内核启动,并且通常会fork其他进程)。

过程创建(通过fork等….)是相当有效的。 一个shell几乎可以分出所有的命令(除了内置的命令,比如cd或者ulimit )。 clone是多线程所必需的(但可以用来替代fork

注意system(3) , popen(3)是库函数 (不是系统调用 ,在syscalls(2) …中列出)调用forkexecve (on /bin/sh …),而守护进程3)是一个库函数调用fork (两次)等…

使用strace(1) (找出哪个系统调用程序正在执行)并阅读高级Linux编程

现在,最近的Libc使用的clonefork更多(有些不再调用fork syscall,而只是clone ); 你可以有几个libc,例如MUSL libc (或者替代) GNU libc