system()
和 popen()
是 C 语言中用于执行外部命令的两个函数,它们的功能类似,但在使用方式和特性上有一些区别。
system()
system()
函数允许您在程序中执行外部命令,并等待该命令执行完成后继续执行程序。其基本语法如下:
int system(const char *command);
-
command
是一个字符串,包含您要执行的命令。这可以是任何有效的命令,就像您在命令行中输入的一样。 -
system()
函数将返回执行结果。如果成功执行了命令,则返回值为命令的退出状态码。如果无法执行命令,则返回 -1。 -
system()
函数会阻塞当前进程,直到执行的命令完成。
示例:
#include <stdio.h>
#include <stdlib.h>
int main() {
int status = system("ls -l");
if (status == -1) {
printf("Failed to execute command\n");
} else {
printf("Command executed successfully with exit status: %d\n", status);
}
return 0;
}
执行结果:
popen()
popen()
函数允许您在程序中执行外部命令,并建立一个到该命令的管道,可以通过管道进行输入和输出。其基本语法如下:
-
command
和mode
参数分别与system()
函数的参数相同,用于指定要执行的命令和管道的打开模式。 -
popen()
函数返回一个指向 FILE 结构的指针,您可以使用该指针来读取或写入命令的输入和输出。 -
popen()
函数允许并发执行多个命令,并且可以通过管道进行通信。
示例:
#include <stdio.h>
int main() {
FILE *fp;
char buffer[1024];
fp = popen("ls -l", "r");
if (fp == NULL) {
printf("Failed to execute command\n");
return 1;
}
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
}
pclose(fp);
return 0;
}
执行结果:
这段代码的作用是执行一个外部命令 ls -l
(列出当前目录下的文件和文件夹,并显示详细信息),并将命令的输出逐行打印到标准输出(终端)上。
让我们逐行解释代码:
-
#include <stdio.h>
:包含了标准输入输出的头文件。 -
int main()
:主函数的定义。 -
FILE *fp;
:声明了一个指向FILE
结构的指针fp
,它将被用作popen()
返回的管道。 -
char buffer[1024];
:声明了一个用于存储命令输出的缓冲区。 -
fp = popen("ls -l", "r");
:调用popen()
函数执行外部命令ls -l
,并将其输出连接到管道上。模式"r"
表示只读模式,因此fp
将用于从管道读取命令的输出。 -
if (fp == NULL)
:检查popen()
函数的返回值,如果返回空指针,则表示执行命令失败。 -
printf("Failed to execute command\n");
:打印错误信息。 -
return 1;
:退出程序,返回错误代码。 -
while (fgets(buffer, sizeof(buffer), fp) != NULL)
:使用fgets()
函数从管道中读取命令的输出,并将其逐行存储到buffer
缓冲区中。循环会继续,直到fgets()
函数返回NULL
,表示已经读取完全部输出。 -
printf("%s", buffer);
:打印缓冲区中的内容,即命令的输出。 -
pclose(fp);
:关闭由popen()
打开的管道,并等待命令执行完毕。 -
return 0;
:退出程序,返回成功代码。
system 和 popen的区别:
-
返回类型:
system()
返回命令的退出状态码。popen()
返回一个文件指针,用于读取或写入命令的输入和输出。
-
阻塞特性:
system()
函数会阻塞当前进程,直到执行的命令完成。popen()
函数允许并发执行多个命令,并且您可以在不等待命令完成的情况下继续执行程序。
-
输入输出:
system()
函数只能捕获命令的退出状态码,无法直接获取命令的输入和输出。popen()
函数可以通过管道进行输入和输出,允许更灵活的交互。
综上所述,如果您只需要执行简单的命令并等待其完成,可以使用 system()
函数。如果您需要与命令进行交互,或者需要同时执行多个命令,可以使用 popen()
函数。
问:是不是虽然没有ls -l的运行结果没在终端显示,但是它已经执行了?
是的,即使没有使用 printf
或其他输出函数将 popen()
命令的输出显示在终端上,该命令仍然会在后台执行,并将结果写入到管道中。
即便没有读取管道中的输出,popen()
也会执行给定的命令,并等待命令执行完成。只是程序没有处理这些输出而已。