【Qt筆記】進程

進程是操做系統的基礎之一。一個進程能夠認爲是一個正在執行的程序。咱們能夠把進程當作計算機運行時的一個基礎單位。關於進程的討論已經超出了本章的範疇,如今咱們假定你是瞭解這個概念的。數組

在 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,爲了不出現亂碼,咱們必須設置文本的編碼方式。code

通道的術語可能會引發誤會。注意,進程的輸出通道對應着QProcess的  通道,進程的輸入通道對應着QProcess的  通道。這是由於咱們使用QProcess「讀取」進程的輸出,而咱們針對QProcess的「寫入」則成爲進程的輸入。QProcess還能夠合併標準輸出和標準錯誤通道,使用setProcessChannelMode()函數設置MergedChannels便可實現。繼承

另外,QProcess還容許咱們使用setEnvironment()爲進程設置環境變量,或者使用setWorkingDirectory()爲進程設置工做目錄。

前面咱們所說的信號槽機制,相似於前面咱們介紹的QNetworkAccessManager,都是異步的。與QNetworkAccessManager不一樣在於,QProcess提供了同步函數:

  • waitForStarted():阻塞到進程開始;
  • waitForReadyRead():阻塞到能夠從進程的當前讀通道讀取新的數據;
  • waitForBytesWritten():阻塞到數據寫入進程;
  • waitForFinished():阻塞到進程結束;

注意,在主線程(調用了QApplication::exec()的線程)調用上面幾個函數會讓界面失去響應。

相關文章
相關標籤/搜索