Linux中“系统”和“执行”之间的区别?


72

systemexec家庭命令有什么区别?特别是我想知道其中哪个创建了子流程?

Answers:


95

system()调用sh以处理您的命令行,因此您可以进行通配符扩展等。 exec()它的朋友可以用新的过程映像替换当前过程映像。

使用system(),您的程序将继续运行,您将获得有关所调用外部命令的某些状态。使用exec(),您的过程将消失。

通常,我想您可以将其system()视为更高级别的界面。你可以使用一些组合复制它的功能你自己fork()exec()wait()

要回答您的最后一个问题,将system()导致创建子进程,而exec()家庭则不会。您将需要使用fork()它。


system调用是否也产生一个新的Shell来执行给定的命令,或者在同一Shell中执行该命令。
克里希纳(Krishna Oza)

@Krishna_Oza-没有“相同的外壳”,除非程序调用system()本身就是外壳。我不确定是否要遵循。我在这里的文档说:“该system()函数将自变量命令交给命令解释器sh(1)。”
卡尔·诺鲁姆

3
从报价systemPOSIX手册system()功能应行为,如果一个子进程所使用的创作fork(),和子进程使用调用的SH工具execl()如下:execl(<shell path>, "sh", "-c", command, (char *)0);
patryk.beza

20

成功时,exec函数将替换当前正在运行的过程映像,不会创建任何子级(除非您以前使用来进行此操作fork())。system()函数确实派生一个子进程,并在提供的命令完成执行或发生错误时返回。


7

system()将在它产生的子进程中执行提供的命令。exec()将用您指定的新可执行文件的调用替换当前进程。如果您想使用生成一个子进程exec,则必须fork()事先进行该过程。


6

创建过程:

  • fork(2),系统直接调用内核

要执行程序,请替换当前图像:

  • execve(2),系统直接调用内核,通常只是调用 exec

等待子进程完成:

  • wait(2),系统直接调用内核

要在子进程的外壳程序中运行程序并等待其完成:

  • system(3),一个库函数

要获取以上所有内容的手册页


2

system()将调用系统的默认命令外壳,该外壳将执行作为参数传递的命令字符串,它本身可能会或可能不会创建进一步的进程,这将取决于命令和系统。无论哪种方式,都将至少创建一个命令外壳进程。

使用system()可以调用任何命令,而使用exec()则只能调用可执行文件。Shell脚本和批处理文件必须由命令Shell执行。

基本上,它们用于不同目的完全不同。而且exec()替换了调用过程,并且不返回。一个更有用的比较是在system()和spawn()之间。虽然system可能更易于调用,但它会返回一个值,该值告诉您是否已调用命令外壳程序,并且不告诉您命令本身是否成功。使用spawn()可以获取进程的退出代码。按照惯例,非零用于指示错误情况。像exec()一样,spawn()必须调用可执行文件,而不是Shell脚本或内置命令。


2

例如: system("date > file");


通常,系统是通过调用fork,exec和waitpid来实现的,返回值有三种类型。

  • 如果fork失败或waitpid返回EINTR以外的错误,则系统将返回–1并设置errno来指示错误。
  • 如果exec失败,则表明无法执行该Shell,则返回值就好像该Shell已执行exit(127)。
  • 否则,所有三个功能(fork,exec和waitpid)都会成功,并且系统返回的值是shell的终止状态,采用为waitpid指定的格式。

的功能是创建一个新的过程(子),其然后导致另一个程序通过调用的一个被执行的exec功能。当某个进程调用exec函数之一时,该进程将被新程序完全替换,新程序将在其主要功能处开始执行。进程ID在整个exec中不会更改,因为不会创建新的进程。exec只是用磁盘上的全新程序替换了当前进程(其文本,数据,堆和堆栈段)。

有六个不同的exec函数




1

exec()用正在执行的功能的过程映像替换当前正在运行的过程。只能使用此文件来调用可执行文件。

system()隐式派生一个新进程来处理请求,并返回通过其最初派生的子进程获得的值,它使用系统的默认Shell进行操作。


1

之间exec(2)和之间system(3)应牢记一些重大差异。 system()返回到调用者,而exec()用新图像替换现有代码。上面已经解释了这一点。

但是,当您要运行一个过程然后返回到现有代码,并从被调用过程中接收返回代码时,并没有那么微妙的区别。 system()确实提供了返回码,但是该返回码只能用于检测错误情况,而不能用于恢复返回码。

系统调用的一种可能的适当顺序是:

可以通过仔细阅读相关手册页来确定此序列的其他细微之处,但是在没有信号,多个子进程等的情况下,此代码也可以正常工作。此外,内联声明可能会限制变量,但包含这些变量是为了允许将此代码用作有效的模板(您可以使用其他编码样式:-)。


1

JonSpencer的答案很好,除了child_status必须是一个int(没有指向int的指针)并且必须通过引用传递给wait函数。

因此,代码基本上是相同的,只是更改了以下几点:

(指出我还没有足够的声誉来评论Jon的帖子,所以我对其进行了编辑。有​​些人拒绝了该版本,要求我回答问题而不是对其进行编辑,但是我认为在这种情况下,它更加简单,实用并明确地编辑一个现有的代码仅能纠正一个小错误,而不是编写完整的复制/粘贴/修改答案。


0

System()将创建子进程并调用另一个子外壳,而exec()不会创建子进程。给出的示例将清除差异。

一些代码...

exec('ls -l')

echo“ 1 2 3” //这不会在bash中执行(因为exec命令使用相同的shell)

一些代码...

系统(ls -l)echo“ 1 2 3” //这将在完成系统子进程后执行,因为它们与父PID不同。


0

system()使用Shell调用所需的程序或内置命令,这是一种低效的方式,因为在启动程序之前先启动Shell。

对于exec系列的系统调用,将创建一个全新的映像,即它们用路径或文件或您要提及的任何参数指定的新进程替换当前进程。

要记住的是,当使用exec系列系统调用时,新程序启动后,原始程序将不再运行。


0

通常,“系统”的效率很低,除非代码很小,否则不应使用它。如果您需要在流程中执行多个程序,则最好使fork&exec更为复杂。以下是它们之间的差异列表:

1-“ system”命令创建一个Shell副本来执行您的程序。每次调用系统时,都会创建一个shell副本。因此,当您在进程中要执行许多程序时,请不要使用它。

2-具体来说,如果要执行“ mv”,“ mkdir”之类的系统功能,最好使用mkdir(),unlink()或remove()之类的例程,而不要通过“ system(”)执行它们rm ....“)或system(” mkdir ....“)”。

3-由于系统调用Shell来执行所需的程序,因此您可能会遇到一些用户权限问题。例如,某人可能会破解您的代码并执行其他操作,而不是您打算通过系统命令执行的程序。

有关更多信息,您可以阅读本书的第11章:David Curry的“ UNIX系统编程”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.