2013-04-26 93 views
0

我正在1赫茲的計時器插槽中運行QProcess。該過程旨在喚起Linux命令並解析其輸出。QProcess,無法創建管道

問題是這樣的:節目約20分鐘一班後,我得到這個錯誤:

QProcessPrivate::createPipe: Cannot create pipe 0x104c0a8: Too many open files 
QSocketNotifier: Invalid socket specified 

理想的情況下,該程序將運行在系統的整個運行時間,這可能是數天或數週。

我想我已經通過閱讀示例小心處理過程控制,但也許我錯過了一些東西。我使用了Qt網站的示例,它們使用了我編寫的相同代碼,但這些代碼是爲單次使用而設計的,而不是數千次。下面是一個最小例如:

class UsageStatistics : public QObject { 
    Q_OBJECT 
public: 
    UsageStatistics() : process(new QProcess) { 
     timer = new QTimer(this); 
     connect(timer, SIGNAL(timeout()), this, SLOT(getMemoryUsage())); 
     timer->start(1000); // one second 
    } 

    virtual ~UsageStatistics() {} 

public slots: 

    void getMemoryUsage() { 
     process->start("/usr/bin/free"); 
     if (!process->waitForFinished()) { 
      // error processing 
     } 

     QByteArray result = process->realAll(); 
     // parse result 

     // edit, I added these 
     process->closeReadChannel(QProcess::StandardOutput); 
     process->closeReadChannel(QProcess::StandardError); 
     process->closeWriteChannel(); 
     process->close(); 
    } 
} 

我也手動deleting試圖處理指針在函數的末尾,然後new開頭。我想這是值得一試的。

免費啤酒誰回答了這個:)

+0

您在某處泄漏句柄,或者您同時啓動了太多QProcess-es。看到https://bugreports.qt-project.org/browse/QTBUG-18934 – sashoalm 2013-04-26 13:44:22

+0

這不是你的問題的答案,但如果你的目標是要找出系統中有多少內存是空閒的,我建議完全避免QProcess並使用更輕量級的機制,如fopen(「/ proc/meminfo」,「r」),並直接讀出數據。效率更高,錯誤更少:) – 2013-04-26 14:47:09

回答

1

QProcessQIODevice得來,所以我會說打電話close()應該關閉文件句柄並解決你的問題。

+0

直接運行16:00,然後出現相同錯誤,即使使用'close()' – 2013-04-26 13:49:19

1

我看不到問題,但是有一件事關注的是getMemoryUsage()中的一個可能的調用重疊,它在上一次運行完成之前被調用。

重構這個以便在getMemoryUsage()(堆棧上,而不是new'd)內使用新的QProcess對象,而不是作爲頂級類的實例變量?這將確保清理(QProcess對象超出範圍),並可避免任何可能的調用重疊。

另外,爲什麼不直接自己讀/proc/meminfo作爲一個過程並解析其輸出,而不是調用/usr/bin/free?這將是更有效率。

+0

我並不直接直接讀取'/ proc/meminfo',因爲解析起來更加困難。實際上我有一個功能,但是當進行基準測試時,我發現性能差異可以忽略不計,所以我選擇了易於理解的代碼。但是,如果'QProcess'不能平移,我只會使用原始的解析函數。 – 2013-04-26 16:21:53

+0

系統調用[sysinfo](http://man7.org/linux/man-pages/man2/sysinfo.2.html)如何?這個調用還會返回linux上的可用內存。 – cloose 2013-04-26 17:03:13

1

首先我和你有同樣的情況。我得到了同樣的結果。 我認爲QProcess無法正確處理打開的管道。

然後,而不是QProcess,我決定使用popen()+ QFile()。

class UsageStatistics : public QObject { 
Q_OBJECT 
public: 
UsageStatistics(){ 
    timer = new QTimer(this); 
    connect(timer, SIGNAL(timeout()), this, SLOT(getMemoryUsage())); 
    timer->start(1000); // one second 
} 

virtual ~UsageStatistics() {} 

private: 
    QFile freePipe; 
    FILE *in; 

public slots: 

void getMemoryUsage() { 

    if(!(in = popen("/usr/bin/free", "r"))){ 
      qDebug() << "UsageStatistics::getMemoryUsage() <<" << "Can not execute free command."; 
      return; 
    } 

    freePipe.open(in, QIODevice::ReadOnly); 
    connect(&freePipe, SIGNAL(readyRead()), this, SLOT(parseResult())); 
    // OR waitForReadyRead() and parse here. 
} 

void parseResult(){ 
    // Parse your stuff 
    freePipe.close(); 
    pclose(in); // You can also use exit code by diving by 256. 
} 
}