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

发布于 2024-08-10 09:00:27 字数 82 浏览 6 评论 0原文

systemexec 系列命令之间有什么区别?特别是我想知道他们中的哪一个创建子进程来工作?

What is the difference between system and exec family commands? Especially I want to know which one of them creates child process to work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

不知所踪 2024-08-17 09:00:27

system() 调用 sh 来处理你的命令行,这样你就可以获得通配符扩展等。 exec() 及其朋友替换当前过程映像与新过程映像。

使用system(),您的程序将继续运行,并返回有关您调用的外部命令的一些状态。使用exec(),您的进程将被删除。

一般来说,我想您可以将 system() 视为更高级别的接口。您可以使用 fork()exec()wait() 的某种组合自行复制其功能。

为了回答您的最后一个问题,system() 会导致创建子进程,而 exec() 系列则不会。为此,您需要使用fork()

system() calls out to sh to handle your command line, so you can get wildcard expansion, etc. exec() and its friends replace the current process image with a new process image.

With system(), your program continues running and you get back some status about the external command you called. With exec(), your process is obliterated.

In general, I guess you could think of system() as a higher-level interface. You could duplicate its functionality yourself using some combination fork(), exec(), and wait().

To answer your final question, system() causes a child process to be created, and the exec() family do not. You would need to use fork() for that.

情栀口红 2024-08-17 09:00:27

成功后,exec 函数会替换当前正在运行的进程映像,不会创建子进程(除非您之前使用 fork() 自己创建了此操作)。 system() 函数会分叉一个子进程,并在提供的命令执行完毕或发生错误时返回。

The exec function replace the currently running process image when successful, no child is created (unless you do that yourself previously with fork()). The system() function does fork a child process and returns when the command supplied is finished executing or an error occurs.

梦太阳 2024-08-17 09:00:27

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

system() will execute the supplied command in a child process that it spawns. exec() will replace the current process with the invocation of the new executable that you specify. If you want to spawn a child process using exec, you'll have to fork() your process beforehand.

旧伤还要旧人安 2024-08-17 09:00:27

要创建进程:

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

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

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

等待子进程完成:

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

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

  • system(3) ,一个库函数

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

   $ man 2 fork execve wait
   $ man 3 system

To create a process:

  • fork(2), a system call directly to the kernel

To execute a program, replacing the current image:

  • execve(2), a system call directly to the kernel, usually just called exec

To wait for a child process to finish:

  • wait(2), a system call directly to the kernel

To run a program in a shell in a child process and wait for it to finish:

  • system(3), a library function

To get the man pages for all of the above:

   $ man 2 fork execve wait
   $ man 3 system
淡水深流 2024-08-17 09:00:27

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

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

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

system() will invoke your systems default command shell, which will execute the command string passed as an argument, that itself may or may not create further processes, that would depend on the command and the system. Either way, at least a command shell process will be created.

With system() you can invoke any command, whereas with exec(), you can only invoke an executable file. Shell scripts and batch files must be executed by the command shell.

Basically they are entirely different used for different purposes. Moreover exec() replaces the calling process, and does not return. A more useful comparison would be between system() and spawn(). While system may be simpler to invoke, it returns a value that tells you whether the command shell was invoked, and tells you nothing about the success of the command itself. With spawn() you can get the process's exit code; by convention non-zero is used to indicate error conditions. Like exec() spawn() must invoke an executable, not a shell script or built-in command.

西瓜 2024-08-17 09:00:27

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

所以,代码基本上是相同的,只是改变了这几件事:(

#include <unistd.h>
#include <sys/wait.h>
#define NUMARGS 2

int main (int argc, char *argv[])
{
  pid_t child_pid, wait_pid;
  int child_status;
  char * exec_path = "/path/to/executable";
  char * child_args[NUMARGS] = {0,0};

  child_pid = fork();
  if (0 == child_pid)
  { // In child process
     ...
     int child_ret_code = execv(exec_path, child_args);  //or whichever flavor of exec() that floats your boat
     ... // if child_ret_code = -1, process execv() error return
  }
  else if (-1 == child_pid)
  {
     ... //process error return from fork
  }
  else if (0 < child_pid)
  {  // Parent process
     wait_pid = wait(&child_status);
     if (-1 == wait_pid)
     {
       ... //Process error return from wait()
     }
     else
     {  //  Good fork/exec/wait
        if (WIFEXITED(child_status))  // Child exited normally and hopefully returned exit code
        {
           int child_ret_code = WEXITSTATUS(child_status);
           ...  // Continue on as you would after call to system(3)
                //   except now you have the return code you needed
        }
     }
  }
}

指出我还没有足够的声誉来评论乔恩的帖子,所以我编辑了它。有些人拒绝了要求我回答问题的版本编辑它,但我认为在这种情况下,编辑现有代码只是纠正一个小错误比编写完整的复制/粘贴/修改答案要简单、实用和清晰。)
无论如何,感谢 JonSpencer 的回答,这对我来说非常有用!

JonSpencer answer is fine, except that child_status must be an int (no a pointer to int) and has to be passed to wait function by reference.

So, the code would be mainly the same, just changing those couple of things:

#include <unistd.h>
#include <sys/wait.h>
#define NUMARGS 2

int main (int argc, char *argv[])
{
  pid_t child_pid, wait_pid;
  int child_status;
  char * exec_path = "/path/to/executable";
  char * child_args[NUMARGS] = {0,0};

  child_pid = fork();
  if (0 == child_pid)
  { // In child process
     ...
     int child_ret_code = execv(exec_path, child_args);  //or whichever flavor of exec() that floats your boat
     ... // if child_ret_code = -1, process execv() error return
  }
  else if (-1 == child_pid)
  {
     ... //process error return from fork
  }
  else if (0 < child_pid)
  {  // Parent process
     wait_pid = wait(&child_status);
     if (-1 == wait_pid)
     {
       ... //Process error return from wait()
     }
     else
     {  //  Good fork/exec/wait
        if (WIFEXITED(child_status))  // Child exited normally and hopefully returned exit code
        {
           int child_ret_code = WEXITSTATUS(child_status);
           ...  // Continue on as you would after call to system(3)
                //   except now you have the return code you needed
        }
     }
  }
}

(Point out that I don't have enough reputation yet to comment Jon's post so I edited it. Some people rejected the edition asking me to answer the question instead of editing it, but I think that in this case it is much simpler, practical and clear to edit an existing code just correcting a small mistake than to write a full copy/paste/modify answer.)
Anyway, thanks JonSpencer for your answer, it was really useful for me!

半世晨晓 2024-08-17 09:00:27

int system(const char *cmdstring);

Ex: system("date > file");


一般来说,system是通过调用fork、exec、waitpid来实现的,有三种类型的返回值。

  • 如果 fork 失败或 waitpid 返回 EINTR 以外的错误,系统将返回 –1 并设置 errno
    以指示错误。
  • 如果exec失败,意味着shell无法执行,返回值就像shell已经执行一样
    退出(127)。
  • 否则,所有三个函数(fork、exec 和 waitpid)都会成功,并且系统返回值
    是 shell 的终止状态,采用为 waitpid 指定的格式。

fork 函数是创建一个新进程(子进程),然后
通过调用 exec 函数之一来执行另一个程序。当一个进程调用其中之一时
exec 函数,该进程完全被新程序替换,新程序开始执行
其主要功能。进程 ID 在执行过程中不会改变,因为没有创建新进程;执行
只是用一个全新的程序替换当前进程(它的文本、数据、堆和堆栈段)
磁盘。

有六种不同的执行函数


int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );

int execv(const char *pathname, char *const argv []);

int execle(const char *pathname, const char *arg0, .../* (char *)0, char *const envp[] */ );

int execve(const char *pathname, char *const argv[], char *const envp []);

int execlp(const char *filename, const char *arg0,... /* (char *)0 */ );

int execvp(const char *filename, char *const argv []);


int system(const char *cmdstring);

Ex: system("date > file");


In general, system is implemented by calling fork, exec, and waitpid, there are three types of return values.

  • If either the fork fails or waitpid returns an error other than EINTR, system returns –1 with errno set
    to indicate the error.
  • If the exec fails, implying that the shell can't be executed, the return value is as if the shell had executed
    exit(127).
  • Otherwise, all three functions—fork, exec, and waitpid—succeed, and the return value from system
    is the termination status of the shell, in the format specified for waitpid.

The fork function is to create a new process (the child) that then
causes another program to be executed by calling one of the exec functions. When a process calls one of the
exec functions, that process is completely replaced by the new program, and the new program starts executing
at its main function. The process ID does not change across an exec, because a new process is not created; exec
merely replaces the current process—its text, data, heap, and stack segments—with a brand new program from
disk.

There are six different exec functions,


int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );

int execv(const char *pathname, char *const argv []);

int execle(const char *pathname, const char *arg0, .../* (char *)0, char *const envp[] */ );

int execve(const char *pathname, char *const argv[], char *const envp []);

int execlp(const char *filename, const char *arg0,... /* (char *)0 */ );

int execvp(const char *filename, char *const argv []);

紧拥背影 2024-08-17 09:00:27

exec() 将当前正在运行的进程替换为正在执行的函数的进程映像。使用此函数只能调用可执行文件。

system() 隐式派生出一个新进程来服务请求,并返回通过最初派生的子进程获得的值。它使用系统的默认 shell 来执行该操作。

exec() replaces the current running process with the process image of the function being performed..only executable files can be invoked using this.

system() forks off a new process implicitly to service the request and returns the value it obtained through the child process it forked initially.It uses the system's default shell to carry out the operation.

聆听风音 2024-08-17 09:00:27

应该牢记 exec(2)system(3) 之间存在一些显着差异。 system() 返回给调用者,而 exec() 用新图像替换现有代码。这已经在上面解释过。

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

系统调用的一种可能的正确顺序是:

#include <unistd.h>
#include <sys/wait.h>
#define NUMARGS 2

int main (int argc, char *argv[])
{
  pid_t child_pid, wait_pid;
  int * child_status;
  char * exec_path = "/path/to/executable";
  char * child_args[NUMARGS] = {0,0};

  child_pid = fork();
  if (0 == child_pid)
  { // In child process
     ...
     int child_ret_code = execv(exec_path, child_args);  //or whichever flavor of exec() that floats your boat
     ... // if child_ret_code = -1, process execv() error return
  }
  else if (-1 == child_pid)
  {
     ... //process error return from fork
  }
  else if (0 < child_pid)
  {  // Parent process
     wait_pid = wait(child_status);
     if (-1 == wait_pid)
     {
       ... //Process error return from wait()
     }
     else
     {  //  Good fork/exec/wait
        if (WIFEXITED(child_status))  // Child exited normally and hopefully returned exit code
        {
           int child_ret_code = WEXITSTATUS(child_status);
           ...  // Continue on as you would after call to system(3)
                //   except now you have the return code you needed
        }
     }
  }
}

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

There are some significant differences between exec(2) and system(3) that should be kept in mind. system() returns to the caller, whereas exec() replaces the existing code with the new image. This has been explained above.

However, the not so subtle difference comes when you want to run a procedure and then return to your existing code, receiving the return code from the invoked procedure. system() does provide a return code, but the return code can only be used to detect an error condition, and cannot be used to recover a return code.

One possible proper sequence of system calls is:

#include <unistd.h>
#include <sys/wait.h>
#define NUMARGS 2

int main (int argc, char *argv[])
{
  pid_t child_pid, wait_pid;
  int * child_status;
  char * exec_path = "/path/to/executable";
  char * child_args[NUMARGS] = {0,0};

  child_pid = fork();
  if (0 == child_pid)
  { // In child process
     ...
     int child_ret_code = execv(exec_path, child_args);  //or whichever flavor of exec() that floats your boat
     ... // if child_ret_code = -1, process execv() error return
  }
  else if (-1 == child_pid)
  {
     ... //process error return from fork
  }
  else if (0 < child_pid)
  {  // Parent process
     wait_pid = wait(child_status);
     if (-1 == wait_pid)
     {
       ... //Process error return from wait()
     }
     else
     {  //  Good fork/exec/wait
        if (WIFEXITED(child_status))  // Child exited normally and hopefully returned exit code
        {
           int child_ret_code = WEXITSTATUS(child_status);
           ...  // Continue on as you would after call to system(3)
                //   except now you have the return code you needed
        }
     }
  }
}

There are other subtleties to this sequence which can be determined by a careful reading of the relevant man pages, but this code will work fine in the absence of signals, multiple child processes, etc. Also, the inline declarations may limit the scope of the variables, but are included to allow this code to be used as a template that works (you may use a different coding style :-).

远昼 2024-08-17 09:00:27

System() 将创建子进程并调用另一个子 shell,而 exec() 将不会创建子进程。给定的示例将明显区别。

some code...

exec('ls -l')

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

some code ...

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

System() will create child process and invoke another sub shell while exec() will not create child process.Given Example will clear difference.

some code...

exec('ls -l')

echo "1 2 3" // This will not executed in bash (as exec command use same shell)

some code ...

system (ls -l)
echo "1 2 3" // This will be executed after finishing System child process as they are different from parent PID.

庆幸我还是我 2024-08-17 09:00:27

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

对于 exec 系列系统调用,正在创建一个全新的映像,也就是说,它们用由路径或文件或您提到的任何参数指定的新进程替换当前进程。

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

system() invokes the desired program or built-in command using a shell, this is an inefficient way because a shell is started before the program is started.

In the case of the exec family of system calls, a whole new image is being created, that is, they replace the current process with a new process specified by the path or file or whatever argument you are mentioning.

The thing to be kept in mind is that, when the exec family of system calls are used, the original program will no longer be running after the new one is started.

遗忘曾经 2024-08-17 09:00:27

一般来说,“系统”效率很低,除非您的代码很小,否则不应该使用它。如果你需要在你的进程中执行多个程序,你最好使用fork&exec,尽管这会让它变得更复杂。
以下是它们之间的差异列表:

1-“system”命令创建 shell 的副本来执行您的程序。每次调用系统时,都会创建 shell 的副本。因此,当您的进程内有大量程序要执行时,请勿使用它。

2-具体来说,如果你想执行“mv”、“mkdir”等系统函数,最好使用mkdir()、unlink()或remove()等例程,而不是通过“system(”执行它们rm ....") 或 system("mkdir ....")"。

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

欲了解更多信息,您可以阅读本书第11章:
David Curry 的《UNIX 系统编程》。

In general, "system" is so inefficient and you should not use it unless you have a small code. If you need to execute several programs in your process, you would better use fork&exec though you make it more complicated.
Here is a list of differences between them:

1- "system" command creates a copy of shell to execute your program. Every time you call a system, you create a copy of shell. So do not use it when you have lots of programs to execute inside your process.

2- Specifically, if you want to execute system functions such as "mv", "mkdir", it would be better to use routines such as mkdir(), unlink() or remove() instead of executing them through "system("rm ....") or system("mkdir ....")".

3- Since system calls shell to execute your desired program, you may have some user permission problems. For example, someone may crack your code and execute something else instead of the program you intended to execute through system command.

For more information, you may read chapter 11 of this book:
"UNIX Systems Programming" by David Curry.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文