美文网首页
调用外部程序并获得输出内容

调用外部程序并获得输出内容

作者: moriv4 | 来源:发表于2020-04-23 20:30 被阅读0次

在做软件开发时,为了实现一个复杂功能可能需要调用其他程序。具体功能在子进程中完成,父进程获取子进程的输出来判断结果。例如编程获得硬盘分区信息这个功能。如果自己从头开始写,只能这样实现:读取硬盘前几个扇区获得分区表,再分析表中的内容。如果直接使用Linux自带的lsblk程序就非常简单,因为lsblk可以输出json字符串,父进程获得后解析即可获得分区信息。

下面给出两种实现方案,第一种是用 Linux C 编程,另一种是用Qt框架编程。功能是:父进程创建子进程、等待子进程结束、获得子进程输出。

  1. Linux C
// get sub process's output in parent process using pipe redirection
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <fcntl.h>
#include <error.h>
#define BUFFSIZE 4000

int main()
{
    int pipefd[2];
    pid_t pid;
    if (pipe(pipefd) != 0)
    {
        perror("cannot create pipe");
    }
    pid = fork();
    if (pid == -1)
    {
        perror("cannot fork");
    }
    else if (pid == 0)
    {
        // child process
        close(pipefd[0]);
        int res = dup2(pipefd[1], STDOUT_FILENO);
        if (res != -1)
            execlp("lsblk", "lsblk", "--fs", "-o", "+MODEL,SIZE", "-J", NULL);
        else
        {
            perror("cannot redirect");
            exit(1);
        }
    }
    close(pipefd[1]);
    int status = -1;
    waitpid(pid, &status, 0);

    char buff[BUFFSIZE];
    ssize_t count = 0;
    count = read(pipefd[0], buff, BUFFSIZE - 1);
    if (count > 0)
        buff[count] = '\0';
    else
        perror("read error");

    // is there left data ?
    char test;
    count = read(pipefd[0], &test, 1);

    printf("%s\n", buff);
    if (count == 1)
        fprintf(stderr, "read incomplete data\n");

    close(pipefd[0]);

    return 0;
}

分析:

  • 创建子进程使用 fork() execlp() 函数。
  • 重定向子进程输出:pipe() dup2() 函数。先把子进程的stdout关闭,再把管道 write fd 复制到stdout对应的fd,最后execlp。子进程的输出内容写入管道中。
  • 等待子进程结束:waitpid() 函数。
  • 读取子进程输出:read() 函数,从管道中读取。
  1. Qt
QProcess lsblk;
lsblk.setProgram("lsblk");
lsblk.setArguments(QStringList() << "--fs" << "-o" << "+MODEL,SIZE" << "-J");
lsblk.start();
lsblk.waitForFinished(1000);
if (lsblk.exitCode() == 0)
    qDebug() << lsblk.readAllStandardOutput();
else 
    qDebug() << lsblk.readAllStandardError();

分析:Qt使用面向对象的思想,把进程看做类。进程类QProcess继承了QIODevice类,这样处理输入输出十分方便。使用的时候创建进程对象lsblk,设置参数并执行,等待进程结束后可以直接获取输出内容。

这两种方法对比来看,Qt框架用起来更方便。QProcess封装了各种底层操作,同时提供强大的进程同步的函数,能轻松实现计时、读取、写入功能,还不需要担心缓冲区溢出的问题。

相关文章

  • 调用外部程序并获得输出内容

    在做软件开发时,为了实现一个复杂功能可能需要调用其他程序。具体功能在子进程中完成,父进程获取子进程的输出来判断结果...

  • golang读取外部命令的屏幕输出

    golang调用外部程序,如何读取外部程序的stdout/stderr输出: 例子1 读取标准输出 运行结果: c...

  • ffmpeg实用功能

    ffmpeg/ffprobe查看音频视频文件信息并输出为json格式,这是一个很实用的功能,特别是外部程序调用并处...

  • go语言得到子程序的返回值

    go语言调用外部程序,并获取外部程序的返回值。 例子1: 程序返回0 运行结果 例子2:程序返回非零 运行结果 这...

  • Mac OSX 开发入门基础系列之NSTask

    利用NSTask,我们可以在应用中调用外部程序或脚本并获得它的<执行状态和结果NSTask最为常用的一个场景是为命...

  • sublime3 build system

    build system运行外部的程序来处理你的项目文件并且打印捕获的输出到sublime的输出面板。最后,调用s...

  • MySQL调优实战之性能剖析,调优中的基础

    性能优化:减少或者消除那些对获得查询结果来说不必要的工作 程序性能瓶颈可能有很多因素:①、外部资源,比如调用了外部...

  • PHP 调用Python脚本

    1. PHP如何调用外部程序 首先要解决的问题就是php如何调用python脚本,在PHP中调用外部程序主要有两个...

  • Java运行系统命令

    java通过Runtime.exec()调用操作系统的系统命令,并获得命令的输出(stdout和stderr)。 ...

  • QT调用外部程序

    1、通过调用Linux C 函数 system("calc.exe"); 2、通过QProcess 阻塞调用 ...

网友评论

      本文标题:调用外部程序并获得输出内容

      本文链接:https://www.haomeiwen.com/subject/tgqzihtx.html