Qt 学习之路 2(69):进程

进程是操作系统的基础之一。一个进程可以认为是一个正在执行的程序。我们可以把进程当做计算机运行时的一个基础单位。关于进程的讨论已经超出了本章的范畴,现在我们假定你是了解这个概念的。

在 Qt 中,我们使用QProcess来表示一个进程。这个类可以允许我们的应用程序开启一个新的外部程序,并且与这个程序进行通讯。下面我们用一个非常简单的例子开始我们本章有关进程的阐述。

 
 
//!!! Qt5
QString program = "C:/Windows/System32/cmd.exe";
QStringList arguments;
arguments << "/c" << "dir" << "C:\\";
QProcess *cmdProcess = new QProcess;
QObject::connect(cmdProcess, &QProcess::readyRead, [=] () {
QTextCodec *codec = QTextCodec::codecForName("GBK");
QString dir = codec->toUnicode(cmdProcess->readAll());
qDebug() << dir;
});
cmdProcess->start(program, arguments);
1
2
3
4
5
6
7
8
9
10
11
//!!! Qt5
QString program = "C:/Windows/System32/cmd.exe";
QStringList arguments;
arguments << "/c" << "dir" << "C:\\";
QProcess *cmdProcess = new QProcess;
QObject::connect(cmdProcess, &QProcess::readyRead, [=] () {
    QTextCodec *codec = QTextCodec::codecForName("GBK");
    QString dir = codec->toUnicode(cmdProcess->readAll());
    qDebug() << dir;
});
cmdProcess->start(program, arguments);

这是一段 Qt5 的程序,并且仅能运行于 Windows 平台。简单来说,这段程序通过 Qt 开启了一个新的进程,这个进程相当于执行了下面的命令:

 
 
C:\Windows\System32\cmd.exe /c dir C:\
1
C:\Windows\System32\cmd.exe /c dir C:\

注意,我们可以在上面的程序中找到这个命令的每一个字符。事实上,我们可以把一个进程看做执行了一段命令(在 Windows 平台就是控制台命令;在 Linux 平台(包括 Unix)则是执行一个普通的命令,比如 ls)。我们的程序相当于执行了 dir 命令,其参数是 C:\,这是由arguments数组决定的(至于为什么我们需要将 dir 命令作为参数传递给 cmd.exe,这是由于 Windows 平台的规定。在 Windows 中,dir 命令并不是一个独立的可执行程序,而是通过 cmd.exe 进行解释;这与 ls 在 Linux 中的地位不同,在 Linux 中,ls 就是一个可执行程序。因此如果你需要在 Linux 中执行 ls,那么program的值应该就是 ls )。

上面程序的运行结果类似于:

 
 
驱动器 C 中的卷是 SYSTEM

卷的序列号是 EA62-24AB

C:\ 的目录

2013/05/05 20:41 1,024 .rnd
2013/08/22 23:22 <DIR> PerfLogs
2013/10/18 07:32 <DIR> Program Files
2013/10/30 12:36 <DIR> Program Files (x86)
2013/10/31 20:30 12,906 shared.log

2013/10/18 07:33 <DIR> Users
2013/11/06 21:41 <DIR> Windows
2 个文件 13,930 字节
5 个目录 22,723,440,640 可用字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
驱动器 C 中的卷是 SYSTEM
 
卷的序列号是 EA62-24AB
 
C:\ 的目录
 
2013/05/05  20:41             1,024 .rnd
2013/08/22  23:22    <DIR>          PerfLogs
2013/10/18  07:32    <DIR>          Program Files
2013/10/30  12:36    <DIR>          Program Files (x86)
2013/10/31  20:30            12,906 shared.log
 
2013/10/18  07:33    <DIR>          Users
2013/11/06  21:41    <DIR>          Windows
               2 个文件         13,930 字节
               5 个目录 22,723,440,640 可用字节

上面的输出会根据不同机器有所不同。豆子是在 Windows 8.1 64位机器上测试的。

为了开启进程,我们将外部程序名字(program)和程序启动参数(arguments)作为参数传给QProcess::start()函数。当然,你也可以使用setProgram()setArguments()进行设置。此时,QProcess进入Starting 状态;当程序开始执行之后,QProcess进入Running 状态,并且发出started()信号。当进程退出时,QProcess进入NotRunning状态(也是初始状态),并且发出finished()信号。finished()信号以参数的形式提供进程的退出代码和退出状态。如果发送错误,QProcess会发出error()信号

QProcess允许你将一个进程当做一个顺序访问的 I/O 设备。我们可以使用write()函数将数据提供给进程的标准输入;使用read()readLine()或者getChar()函数获取其标准输出。由于QProcess继承自QIODevice,因此QProcess也可以作为QXmlReader的输入或者直接使用QNetworkAccessManager将其生成的数据上传到网络。

进程通常有两个预定义的通道:标准输出通道(stdout)和标准错误通道(stderr)。前者就是常规控制台的输出,后者则是由进程输出的错误信息。这两个通道都是独立的数据流,我们可以通过使用setReadChannel()函数来切换这两个通道。当进程的当前通道可用时,QProcess会发出readReady()信号。当有了新的标准输出数据时,QProcess会发出readyReadStandardOutput()信号;当有了新的标准错误数据时,则会发出readyReadStandardError()信号。我们前面的示例程序就是使用了readReady()信号。注意,由于我们是运行在 Windows 平台,Windows 控制台的默认编码是 GBK,为了避免出现乱码,我们必须设置文本的编码方式。

通道的术语可能会引起误会。注意,进程的输出通道对应着QProcess 通道,进程的输入通道对应着QProcess 通道。这是因为我们使用QProcess“读取”进程的输出,而我们针对QProcess的“写入”则成为进程的输入。QProcess还可以合并标准输出和标准错误通道,使用setProcessChannelMode()函数设置MergedChannels即可实现。

另外,QProcess还允许我们使用setEnvironment()为进程设置环境变量,或者使用setWorkingDirectory()为进程设置工作目录。

前面我们所说的信号槽机制,类似于前面我们介绍的QNetworkAccessManager,都是异步的。与QNetworkAccessManager不同在于,QProcess提供了同步函数:

  • waitForStarted():阻塞到进程开始;
  • waitForReadyRead():阻塞到可以从进程的当前读通道读取新的数据;
  • waitForBytesWritten():阻塞到数据写入进程;
  • waitForFinished():阻塞到进程结束;

注意,在主线程(调用了QApplication::exec()的线程)调用上面几个函数会让界面失去响应。

Qt 学习之路 2(69):进程的更多相关文章

  1. Qt 学习之路 2(71):线程简介

    Qt 学习之路 2(71):线程简介 豆子 2013年11月18日 Qt 学习之路 2 30条评论 前面我们讨论了有关进程以及进程间通讯的相关问题,现在我们开始讨论线程.事实上,现代的程序中,使用线程 ...

  2. Qt 学习之路 2(70):进程间通信

    Qt 学习之路 2(70):进程间通信 豆子 2013年11月12日 Qt 学习之路 2 16条评论 上一章我们了解了有关进程的基本知识.我们将进程理解为相互独立的正在运行的程序.由于二者是相互独立的 ...

  3. Qt 学习之路 2(66):访问网络(2)

    Home / Qt 学习之路 2 / Qt 学习之路 2(66):访问网络(2) Qt 学习之路 2(66):访问网络(2)  豆子  2013年10月31日  Qt 学习之路 2  27条评论 上一 ...

  4. Qt 学习之路 2(51):布尔表达式树模型

    Qt 学习之路 2(51):布尔表达式树模型 豆子 2013年5月15日 Qt 学习之路 2 17条评论 本章将会是自定义模型的最后一部分.原本打算结束这部分内容,不过实在不忍心放弃这个示例.来自于 ...

  5. Qt 学习之路 2(35):文件

    Qt 学习之路 2(35):文件 豆子 2013年1月5日 Qt 学习之路 2 12条评论 文件操作是应用程序必不可少的部分.Qt 作为一个通用开发库,提供了跨平台的文件操作能力.从本章开始,我们来了 ...

  6. Qt 学习之路 2(6):Qt 模块简介

    Home / Qt 学习之路 2 / Qt 学习之路 2(6):Qt 模块简介  豆子  2012年8月26日  Qt 学习之路 2  20条评论 Qt 5 与 Qt 4 最大的一个区别之一是底层架构 ...

  7. Qt 学习之路 2(3):Hello, world!

     豆子  2012年8月22日  Qt 学习之路 2  107条评论 想要学习 Qt 开发,首先要搭建 Qt 开发环境.好在现在搭建 Qt 开发环境还是比较简单的.我们可以到 Qt 官方网站找到最新版 ...

  8. 《Qt 学习之路 2》目录

    <Qt 学习之路 2>目录 <Qt 学习之路 2>目录  豆子  2012年8月23日  Qt 学习之路 2  177条评论 <Qt 学习之路 2>目录 序 Qt ...

  9. QT学习之路--创建一个对话框

    Q_OBJECT:这是一个宏,凡是定义信号槽的类都必须声明这个宏. 函数tr()全名是QObject::tr(),被他处理过的字符串可以使用工具提取出来翻译成其他语言,也就是做国际化使用. 对于QT学 ...

随机推荐

  1. Windchill 设计变更流程卡死查询方法

    设计变更流程卡死查询方法 1. 导出设计变更表单查看填写了“需要”和“是”字眼的文本框  2.打开进程管理器显示流程卡死的地方,确定哪里出错导致没法执行下一步  3.打开设计变更流程图,里面可以查看有 ...

  2. QPS、PV和需要部署机器数量计算公式

    QPS:Queries Per Second意思是“每秒查询率”,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准. TPS是 Transactions ...

  3. c++ 多态问题(在虚函数里调用虚函数)

    最近在看cocos2d-x的源码,非常感激cocos2d作者的开源精神.在看代码的过程中感觉两个方向让我受益,1.把之前从书中看到的c++知识,明白了怎么运用.2.学习作者驾驭代码的巧妙方法. 看co ...

  4. Web服务器父与子 Apache和Tomcat区别(转)

    From http://developer.51cto.com/art/201007/210894.htm 熟悉三国的朋友都知道曹操,曹操有二十五个儿子,其中最得曹操宠爱的是曹丕.曹植.曹彰三个,曹丕 ...

  5. css总结12:CSS Float(浮动)

    1 定义:CSS 的 Float(浮动),会使元素向左或向右移动,其周围的元素也会重新排列. 2 解释:浮动的元素,浮在界面上,脱离了HTML文本流. 元素的水平方向浮动,意味着元素只能左右移动而不能 ...

  6. (转)Asp.net页面生命周期详解任我行(1)-小试牛刀,编写页面代码

    原文地址:http://www.cnblogs.com/xuyubing/archive/2013/10/01/3348344.html 前言 很久很久以前,还是我在学校的时候,我就看了传智里面视频, ...

  7. POJ3026 Borg Maze(bfs求边+最小生成树)

    Description The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of ...

  8. c++基础知识篇:指针

    从面试的反馈来看,这部分可以问的很难. 1.指针与引用的区别 指针是一个变量,用来存放地址的变量.引用是原来变量的存储空间的别名.   2.指针作为参数的要点 a.需要进行指针的合法性检验,防止空指针 ...

  9. c# enum遍历

    public enum Suit { Spades, Hearts, Clubs, Diamonds } //遍历valueforeach (Suit suit in (Suit[]) Enum.Ge ...

  10. 2张图简单分析count(0)与count(*)

    以前一直以为count(0)查询效率比count(*)比较高,原因大概是这么认为count(0)只是第一列进行统计,而count(*)所有列放在一起统计(亲,不要误会,这里不是所有列累加哦) 结果真的 ...