在C++开发中,调用系统命令是常见的需求,比如需要执行shell命令、调用系统工具完成特定任务,不同场景下可以选择不同的实现方式,下面将介绍几种常用的方法。

使用system函数调用系统命令
system是C标准库提供的函数,在C++中也可以直接调用,它是最简单的系统命令调用方式,函数声明在<cstdlib>头文件中。它会调用系统默认的shell来执行传入的命令字符串,执行完成后返回命令的退出状态。
下面是一个简单的使用示例:
#include <cstdlib>
#include <iostream>
int main() {
// 执行系统命令,Windows下可以执行dir,Linux下可以执行ls
int result = system("ls -l");
if (result == 0) {
std::cout << "命令执行成功" << std::endl;
} else {
std::cout << "命令执行失败,退出码:" << result << std::endl;
}
return 0;
}
这种方式的优点是实现简单,跨平台性较好,只要系统支持对应的shell命令就可以执行。缺点是功能有限,无法直接获取命令的输出内容,只能得到最终的退出状态,而且执行时会启动一个shell进程,有一定的性能开销。
使用popen函数获取命令输出
popen函数可以创建一个管道,连接到执行的命令进程,既可以读取命令的输出,也可以向命令输入数据,函数声明在<cstdio>头文件中。它返回一个文件流指针,可以通过标准的文件操作函数读取内容。
下面是读取命令输出的示例:
#include <cstdio>
#include <iostream>
#include <cstring>
int main() {
// 执行命令并打开读取管道,Windows下可以用_popen,Linux下用popen
#ifdef _WIN32
FILE* pipe = _popen("dir", "r");
#else
FILE* pipe = popen("ls -l", "r");
#endif
if (!pipe) {
std::cout << "管道创建失败" << std::endl;
return 1;
}
char buffer[1024];
// 读取命令输出内容
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
std::cout << buffer;
}
// 关闭管道,获取命令退出状态
#ifdef _WIN32
int status = _pclose(pipe);
#else
int status = pclose(pipe);
#endif
std::cout << "命令退出状态:" << status << std::endl;
return 0;
}
popen的优势是可以直接获取命令的标准输出内容,适合需要解析命令返回结果的场景。但是它也不是完全跨平台的,Windows下需要使用_popen和_pclose,而且同样需要依赖系统的shell,执行效率也不高。
调用系统原生进程创建接口
如果需要更精细的控制,比如不需要依赖shell、需要控制进程的生命周期、设置环境变量等,可以调用操作系统的原生进程创建接口。Windows下可以使用CreateProcess函数,Linux下可以使用fork加exec系列函数。
Linux下使用fork和exec
Linux系统中,fork函数用于创建子进程,exec系列函数用于在子进程中替换进程映像执行新的程序,下面是使用示例:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
int main() {
pid_t pid = fork();
if (pid < 0) {
std::cout << "创建子进程失败" << std::endl;
return 1;
} else if (pid == 0) {
// 子进程执行命令,这里执行ls -l
execl("/bin/ls", "ls", "-l", nullptr);
// 如果exec执行失败才会走到这里
std::cout << "执行命令失败" << std::endl;
return 1;
} else {
// 父进程等待子进程结束
int status;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
std::cout << "子进程退出码:" << WEXITSTATUS(status) << std::endl;
}
}
return 0;
}
Windows下使用CreateProcess
Windows系统提供了CreateProcess函数用于创建新的进程,下面是调用示例:
#include <windows.h>
#include <iostream>
int main() {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// 要执行的命令,这里执行cmd /c dir
char cmd[] = "cmd /c dir";
if (!CreateProcess(
nullptr, // 不指定可执行文件模块
cmd, // 命令行字符串
nullptr, // 进程安全属性
nullptr, // 线程安全属性
FALSE, // 不继承句柄
0, // 创建标志
nullptr, // 环境变量
nullptr, // 当前目录
&si, // 启动信息
&pi // 进程信息
)) {
std::cout << "创建进程失败,错误码:" << GetLastError() << std::endl;
return 1;
}
// 等待进程结束
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitCode;
GetExitCodeProcess(pi.hProcess, &exitCode);
std::cout << "进程退出码:" << exitCode << std::endl;
// 关闭句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
这种方式不依赖shell,执行效率更高,功能也更强大,但是完全不跨平台,需要针对不同的操作系统编写不同的代码,使用复杂度也更高。
不同方法的选择建议
如果是简单的命令执行,不需要获取输出,优先选择system函数,实现简单;如果需要获取命令的输出内容,可以选择popen函数;如果对性能、控制精度有较高要求,或者需要避免shell依赖,可以选择系统原生的进程创建接口。如果项目需要跨平台,可以封装一套统一的接口,在不同平台下调用对应的实现。
| 方法 | 跨平台性 | 获取输出 | 复杂度 | 适用场景 |
|---|---|---|---|---|
| system | 较好 | 不支持 | 低 | 简单命令执行,不需要输出 |
| popen | 一般,需处理平台差异 | 支持 | 中 | 需要获取命令输出内容 |
| 原生进程接口 | 差,需分别实现 | 支持 | 高 | 高性能要求、精细控制进程 |
C++system_commandexec_functionpopenprocess_creation修改时间:2026-06-26 00:54:38