关闭

QProcess:进程通信之无名管道

标签: 无名管道IPC进程通信QtC++
2467人阅读 评论(1) 收藏 举报
分类:

进程间通信(IPC)方式包括:管道,FIFO,信号。这里只提下无名管道,用于有亲缘关系的进程之间。有名管道可以用在没有亲缘关系的进程之间。

QProcess,底层使用的就是无名管道。

做了一个小demo,毕设有一块要用到。

由于底层封装了win linux mac不同平台的无名管道实现,避免了无谓的跨平台体力劳动。

但使用QProcess时,要注意:在主进程中向子进程写数据时,数据结尾一定要有换行符,即"\n",否则就如同用标准输入没有按回车一个效果,子进程是不会去处理你输入的数据的,因为子进程认为你还没有输完。

用于子进程的程序:

#include <iostream>
#include <string>
using std::cout;
using std::endl;

int main(void)
{
    cout << "Child Process: I am Ready!" << endl;
    std::string input;
    while(true)
    {
        getline(std::cin,input);
        if(!input.compare("quit"))
            break;
        cout << "From Child Process: " << input << endl;
    }
    cout << "Bye From Child Process!" << endl;
    return 0;
}

用于调用上述子程序的主程序,主程序有三个文件组成

#ifndef PARENT_PROCESS_H
#define PARENT_PROCESS_H
#include <QObject>
class QProcess;

class ParentProcess : public QObject
{
    Q_OBJECT
public:
    explicit ParentProcess(QObject *parent = 0);
    ~ParentProcess();
public slots:
    void sender();
    void receiver();
private:
    QProcess* myChildProcess;
    int count;
};

#endif // PARENT_PROCESS_H


#include "ParentProcess.h"
#include <QProcess>
#include <QDebug>

ParentProcess::ParentProcess(QObject *parent) :
    QObject(parent)
{
    count = 0;
    myChildProcess = new QProcess(this);
    QObject::connect(myChildProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(receiver()));
    myChildProcess->setProcessChannelMode(QProcess::MergedChannels);
    myChildProcess->start("usingQProcess.exe");
    if (!myChildProcess->waitForStarted())
        qDebug() << "Make failed:" << myChildProcess->errorString();
    else
        qDebug() << "Child Process Started. " << myChildProcess->readAll();
}

ParentProcess::~ParentProcess()
{
    myChildProcess->close();
    delete myChildProcess;
    myChildProcess = nullptr;
}

void ParentProcess::sender()
{
   if(count > 3)
       myChildProcess->write("quit\n");
   count++;
   myChildProcess->write("Nice to meet you!");
   myChildProcess->write((QString::number(count)+ "\n").toStdString().c_str());
}

void ParentProcess::receiver()
{
    char output[128];
    int ret = myChildProcess->readLine(output,127);
    qDebug() << ret;
    qDebug() << output;
}


#include "ParentProcess.h"
#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ParentProcess obj;
    QPushButton myBtn;
    myBtn.show();
    QObject::connect(&myBtn,SIGNAL(clicked()),&obj,SLOT(sender()));

    return a.exec();
}

上述程序运行之后,子进程通过标准输入输出 来获取和打印信息,而主程序则通过无名管道,重定向子进程的输入输出。
外部程序未启动时,其状态是NotRunning;
    当启动时,其状态转变为Starting,正在启动,但此时还未调用起来;
    启动之后,继续变为Running,同时发射出started()信号,此时,可以对QProcess进行读写操作了;
    当退出时,其状态改为NotRunning,并发射出finished()信号。finishe()信号会携带退出码和退出状态,可以分别通过exitCode()和exitStatus()来获得。

    当发生错误时,QProcess会发出一个error()信号,同样的,也可以通过error()来获得其错误类型,通过state()获得当前程序的状态。

QProcess继承于QIODevice,因此,我们可以把它当作是一个I/O设备进行读写操作。

QProcess有两种预定义的输出通道:标准输出stdout与标准错误stderr。
    通过setReadChannel()可以选择当前读取输出的通道。
    当通道中的数据准备就绪时,QProcess会发出readyRead()信号。如果是标准输出,则发出readyReadStandardOutput()信号;如果是标准错误,则发出readyReadStandardError()信号。
    常用的读取方式有read(), readAll()或getChar(),也可以通过readAllStandardOutput()和readAllStandardError()读取标准输出和标准错误通道中的数据。
    某些程序需要环境设置才能进行特殊的操作。可以通过setEnvironment()来设置环境变量,通过setWorkingDirectory()来设置工作目录,默认的工作路径是当前调用程序的工作路径。

 QProcess提供了一系列的函数以提到事件循环来完成同步操作:
(1)waitForStarted()          : 阻塞,直到外部程序启动
(2)waitForReadyRead()    : 阻塞,直到输出通道中的新数据可读
(3)waitForBytesWritten()  : 阻塞,直到输入通道中的数据被写入
(4)waitForFinished()        : 阻塞,直到外部程序结束
    如果在主线程(QApplication::exec())中调用这些函数,可能会造成当前用户界面不响应。





0
0
查看评论

Linux下的进程通信方式: 管道通信详解

管道是单向的、先进先出的、无结构的字节流,它把一个进程的输出和另一个进程的输入连接在一起。
  • rl529014
  • rl529014
  • 2016-05-20 21:03
  • 3912

Qt之进程间通信(IPC)

简述进程间通信,就是在不同进程之间传播或交换信息。那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。但是,系统空间却是“公共场所”,所以内核显然可以提供这样的条件。除此以外,那就是双方都可以访问的外设了。在这个意义上,两个...
  • u011012932
  • u011012932
  • 2016-01-26 18:56
  • 9814

QT进程间通信详细介绍及QProcess机制分析

1、QT通信机制 为了更好的实现QT的信息交互,在QT系统中创建了较为完善的通信机制。QT的通信可分为QT内部通信和外部通信两大类。对于这两类通信机制及应用场合做如以下分析: (1)QT内部对象间通信 在图形用户界面编程中,经常需要将一个窗口部件的变化通知给窗口的其它部件使其产生相应的变化...
  • fengel_cs
  • fengel_cs
  • 2015-07-15 15:59
  • 4041

进程间通信:管道及命名管道(代码实现)

管道:1.管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;             2.只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);          ...
  • wangiijing
  • wangiijing
  • 2016-07-07 21:03
  • 2493

Qt 进程间通信(IPC)

Qt 是一个跨平台的应用框架,其进程间通信机制当然可以使用所在平台的进程间通信机制,如在Windows平台上的Message机制、共享内存、文件映射、管道、Socket等。其中,Qt对一些许多平台共有的IPC机制进行了封装。 Qt官方文档中对Qt的IPC机制是这样介绍的: TCP/IP ...
  • luoxinwu123
  • luoxinwu123
  • 2012-09-29 09:35
  • 9353

QT中使用QProcess启用外部程序和关闭外部程序

因为目前的程序需要提供一个文件对比的功能,而目前已经有专门的文本对比软件,所以我打算直接调用外部的文本对比程序。 通过查阅QT的帮助文档,发现了QProcess这个类可以提供这种需求。 我找到的启动外部程序的方法有以下两种: 1、start() void QProcess::start ( ...
  • imxiangzi
  • imxiangzi
  • 2015-10-19 16:02
  • 3581

QProcess处理带管道的shell

代码中需要调用shell,原写法为: QProcess *proc = new QProcess(); QString qCmd = "find ./ -name *.so -print0 | xargs -0 objdump -x | grep -oE \"T_...
  • crazyingBird
  • crazyingBird
  • 2016-06-02 14:26
  • 1605

Qt模块化笔记之core——QProcess控制外部程序

QProcess是一个为进程间通信创建的类。在linux相关系统中,可以很方便地用它
  • xsjqqq123
  • xsjqqq123
  • 2014-05-08 20:58
  • 3049

Qt之进程间通信(QProcess)

简述QProcess可以在应用程序内部与其它进程通信,或启动其它应用程序。与在终端机之类的命令输入窗口上使用名称和参数是一样的,可以使用QProcess提供的函数start()启动进程。可以注册QStringList处理进程后的参数。简述 命令行参数启动 说明 实现 命令行读取 说明 实现 更多参考...
  • u011012932
  • u011012932
  • 2016-01-28 18:44
  • 12059

用QProcess实现父子进程的双向交互

记得以前写过Linux的C程序, 里面用popen打开一个子进程, 这样可以用read/write和子进程通讯, 而在子进程里则是通过从stdin读和向stdout写实现对父进程的通讯。 QProcess的底层实现用的是类似的理念。 QProcess类提供的API让父进程可以轻松地读取子进程stdo...
  • imxiangzi
  • imxiangzi
  • 2015-10-19 16:01
  • 1494
    个人资料
    • 访问:152981次
    • 积分:2641
    • 等级:
    • 排名:第16335名
    • 原创:109篇
    • 转载:20篇
    • 译文:1篇
    • 评论:45条
    最新评论