#(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);
~~~
這是一段 Qt5 的程序,并且僅能運行于 Windows 平臺。簡單來說,這段程序通過 Qt 開啟了一個新的進程,這個進程相當于執行了下面的命令:
~~~
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 可用字節
~~~
上面的輸出會根據不同機器有所不同。豆子是在 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()`的線程)調用上面幾個函數會讓界面失去響應。
- (1)序
- (2)Qt 簡介
- (3)Hello, world!
- (4)信號槽
- (5)自定義信號槽
- (6)Qt 模塊簡介
- (7)MainWindow 簡介
- (8)添加動作
- (9)資源文件
- (10)對象模型
- (11)布局管理器
- (12)菜單欄、工具欄和狀態欄
- (13)對話框簡介
- (14)對話框數據傳遞
- (15)標準對話框 QMessageBox
- (16)深入 Qt5 信號槽新語法
- (17)文件對話框
- (18)事件
- (19)事件的接受與忽略
- (21)事件過濾器
- (22)事件總結
- (23)自定義事件
- (24)Qt 繪制系統簡介
- (25)畫刷和畫筆
- (26)反走樣
- (27)漸變
- (28)坐標系統
- (29)繪制設備
- (30)Graphics View Framework
- (31)貪吃蛇游戲(1)
- (32)貪吃蛇游戲(2)
- (33)貪吃蛇游戲(3)
- (34)貪吃蛇游戲(4)
- (35)文件
- (36)二進制文件讀寫
- (37)文本文件讀寫
- (38)存儲容器
- (39)遍歷容器
- (40)隱式數據共享
- (41)model/view 架構
- (42)QListWidget、QTreeWidget 和 QTableWidget
- (43)QStringListModel
- (44)QFileSystemModel
- (45)模型
- (46)視圖和委托
- (47)視圖選擇
- (48)QSortFilterProxyModel
- (49)自定義只讀模型
- (50)自定義可編輯模型
- (51)布爾表達式樹模型
- (52)使用拖放
- (53)自定義拖放數據
- (54)剪貼板
- (55)數據庫操作
- (56)使用模型操作數據庫
- (57)可視化顯示數據庫數據
- (58)編輯數據庫外鍵
- (59)使用流處理 XML
- (60)使用 DOM 處理 XML
- (61)使用 SAX 處理 XML
- (62)保存 XML
- (63)使用 QJson 處理 JSON
- (64)使用 QJsonDocument 處理 JSON
- (65)訪問網絡(1)
- (66)訪問網絡(2)
- (67)訪問網絡(3)
- (68)訪問網絡(4)
- (69)進程
- (70)進程間通信
- (71)線程簡介
- (72)線程和事件循環
- (73)Qt 線程相關類
- (74)線程和 QObject
- (75)線程總結
- (76)QML 和 QtQuick 2
- (77)QML 語法
- (78)QML 基本元素
- (79)QML 組件
- (80)定位器
- (81)元素布局
- (82)輸入元素
- (83)Qt Quick Controls
- (84)Repeater
- (85)動態視圖
- (86)視圖代理
- (87)模型-視圖高級技術
- (88)Canvas
- (89)Canvas(續)