概述
Linux下,想在C语言中执行命令,大概有三种方法:system、popen、exec。
- system:使用简单,但是只能获取到返回码,不能拿到标准输出和标准错误;
- popen:只能拿标准输出,不能拿到返回码和标准错误(其实可以通过指令重定向的方式将标准错误重定向到标准输出,但是这样做没法判断哪些信息是标准输出,哪此是信息是标准错误)。
- exec:这是一组函数,可以加载一个外部程序到本进程,相当于将外部程序嵌入到本进程中,调用exec函数成功之后,exec后面的代码将不会再被执行。
思路
- 使用
fork
函数,创建一个子进程; - 在子进程中调用
dup2
函数将标准输出和标准错重定向到管道; - 在子进程中调用exec函数加载指令进程
- 在主进程在通过管道接收标准错误和标准输出,通过
wait
获取命令进程退出码。
主要代码如下:
int fd_out[2];
int fd_err[2];
pipe(fd_out);
pipe(fd_err);
pid_t pid = fork();
if (pid == 0) {
close(fd_out[0]);
close(fd_err[0]);
dup2(fd_out[1], STDOUT_FILENO);
dup2(fd_err[1], STDERR_FILENO);
execvp(args[0], args);
// execvp调用失败,直接返回-1
perror("execvp失败");
return -1;
} else if (pid > 0) {
close(fd_out[1]);
close(fd_err[1]);
char buffer[1024] = {0};
// 读取标准输出信息
while(true) {
int len = read(fd_out[0], buffer, sizeof(buffer));
}
// 读取标准错误信息
while(true) {
int len = read(fd_err[0], buffer, sizeof(buffer));
}
close(fd_err[0]);
close(fd_out[0]);
int status = 0;
// 获取进程退出码
wait(&status);
}