我在Linux中创建进程时感到困惑。到目前为止,我认为我们可以通过调用以下系统调用来创建进程。
system()
exec()
系列调用fork()
系统调用但:
system():但是当“系统”系统调用执行shell和shell上的输入可执行文件时,正在创建一个子进程来执行输入。所以shell调用子进程然后我们可以说fork正在为此创建流程。
exec系统调用:当这个系统调用时,用新进程写入当前正在运行的进程。所以它也创建了一个新进程但使用相同的地址空间。我认为它也在调用call fork来创建进程。
我很困惑以上所有这些都是创建新进程或只有fork系统的可行方法。
答案 0 :(得分:11)
exec
系列调用系统不会调用fork
,也不会创建新进程。
它只用新的二进制文件覆盖现有的进程。
在linux
个用户程序中,fork
是创建新流程的唯一功能。虽然fork
内部调用了clone
和其他系统调用
另一方面,system
只是fork
和exec
的包装。创建流程的实际任务由fork
中的system
完成。 因此system
不是创建新流程的方法。
答案 1 :(得分:3)
fork()
会创建您的流程副本。这是您在像Linux这样的POSIX环境中实际创建进程的地方。要准确回答您的问题标题,fork()
是创建流程的唯一方法。
exec()
为您做的是用另一个进程替换进程(例如您刚用fork()
创建的进程),因此exec()
本身不会创建进程但通常伴随着fork()
,因为您通常希望创建另一个与当前流程不同的流程。
在system()
电话下方,只有fork()
后跟exec()
,因此这不是创建流程的新方法。
答案 2 :(得分:3)
在POSIX环境中,您可以通过fork
系统调用创建进程,没有任何异常。 Fork将创建一个过程。
exec
函数族只是将其他程序的二进制加载到当前进程的地址空间(调用exec()系统调用)。
在system()
中,内部使用fork()
后跟exec()
系统调用。
答案 3 :(得分:2)
创建新流程的方法只有两种:系统调用fork
和clone
。
提到的其他功能分为两类:
exec()
family:这些用其他程序替换进程的内容。通常在调用exec()
或fork
后使用clone
来将生成的流程之一转换为所需应用程序的流程。例如,当bash
执行gcc
命令时,它首先会自行分配,然后使用{{{} bash
进程将gcc
个进程中的一个转换为exec()
进程1}}家庭。
system()
系列:它们封装了fork
/ clone
系统调用和相应的exec()
调用,可能会执行连接stdin
之类的奇特内容和stdout
等
请注意,所有这些函数fork()
,clone()
,exec()
,system()
等都是由标准C库定义的系统调用包装器(始终存在) ),而不是系统自称。因此,违反直觉,fork()
是当前系统上clone
系统调用的包装器。这并不重要。但是,C库函数是标准化的,系统调用不是。
从历史上看,fork
是旧的系统调用。虽然定义和使用其语义非常容易,但它总是受到其性能影响:整个过程环境需要(至少在逻辑上)被复制,但是,大部分工作都是无用的,作为最终的过程之一通常会被exec
电话完全覆盖。此外,fork
语义不允许创建线程。由于这些缺点,引入了clone
调用,允许对复制的内容进行细粒度控制,以及在两个进程之间共享的内容,允许pthreads
以{{1}的形式实现}。
答案 4 :(得分:2)
除了所有其他答案之外,并且要挑剔,过程由fork(2)(或过时的vfork(2) ...)和clone(2)系统调用创建(并且不, execve(2)系统调用不创建进程,但通过在同一进程中启动新程序来覆盖其地址空间和状态),但某些进程由内核“神奇地”创建,特别是:
/sbin/init
由内核在启动时启动(如果找不到,则尝试其他一些程序,甚至/bin/sh
....);这是pid 1的过程很早就开始了......
某些内核进程(或内核线程)由内核启动,如kswapd,kworker
(请参阅this问题)等等...我有超过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)是库函数(不是system calls,它们列在syscalls(2) ...中)同时调用{ {1}}和fork
(在execve
上)daemon(3)是一个调用/bin/sh
(两次)等的库函数...
使用strace(1)(找出程序正在执行的系统调用)并阅读Advanced Linux Programming
现在,最近的Libc正在使用fork
以上clone
(有些人不再调用fork
系统调用,只有fork
};你可以有几个libc,例如MUSL libc