2011-06-17 72 views
1

我有一個C++程序,它可以將很多數據連續很長時間記錄到磁盤。因此,我有一個線程監視可用的磁盤空間,一旦它達到一定的百分比,就會執行一些操作。執行系統命令的速度非常慢

這是在一個雙核四核x64 CentOS系統上,並且記錄發生在直接連接的SATA磁盤上,這些磁盤僅用於使用ext3文件系統進行記錄。我通過使用system()發出「df」命令並讀取結果來監視磁盤使用情況。

昨天晚上我運行它時,我注意到在日誌文件中,使用完整的39分鐘來運行該命令來查找磁盤使用情況。

,處理超時的代碼是這樣的:

int DiskSpaceMonitor::handle_timeout(const ACE_Time_Value& time_, const void* pFunc_) 
{ 
    LOG4CXX_TRACE(m_logger, "DiskSpaceMonitor timer fired"); 

    ACE_UINT8 usagePercent = m_diskChecker.getDiskSpaceUsagePercentage(m_monitoredDisk); 

    m_fileRecorder->notifyDiskUsage(usagePercent); 

    return 0; 
} 

調用該函數,它的「DF」:

ACE_UINT8 DiskSpaceChecker::getDiskSpaceUsagePercentage(std::string diskMountPoint) 
{ 
    std::stringstream usageCommand; 
    usageCommand << "df -PH " << diskMountPoint << " | grep -v \"^Filesystem\" | awk '{print $5}' | cut -d'%' -f1 > " << m_mountSpaceFile; 
    system(usageCommand.str().c_str()); 

    std::ifstream inFile(m_mountSpaceFile.c_str(), std::ios::in); 
    if (!inFile) 
    { 
     return 0; 
    } 

    std::string usageStr; 
    inFile >> usageStr; 
    int usage = atoi(usageStr.c_str()); 

    inFile.close(); 

    std::stringstream rmCmd; 
    rmCmd << "rm " << m_mountSpaceFile; 
    system(rmCmd.str().c_str()); 

    LOG4CXX_DEBUG(m_logger, "Disk usage for disk: " << diskMountPoint << " = " << usage << "%"); 

    return usage; 
} 

所以跟蹤記錄語句之間handle_timeout()和調試跟蹤語句在getDiskSpaceUsagePercentage()花了39分鐘。但延遲真的出現在inFile >> usageStr;之前(因爲我可以看到閱讀比例高於預期 - 應該增加1%或更少,但是它跳躍了16%以上)。

爲什麼地獄應該處理運行命令並閱讀它需要花費這麼多時間?

現在我承認在寫入磁盤時磁盤確實有些吱吱作響,但只有一個程序寫入它們,它只寫入一個數據文件和一個索引文件。所以我不明白這應該如何持續這麼久。

作爲一種替代方法,有一種簡單的方法可以調用system()函數,並在超時後返回它,如果它耗時過長?

+0

我不確定,但是'getrusage'可以作爲選擇嗎? – 2011-06-17 08:03:41

+0

在這種緩慢的反應過程中,瞭解艾奧瓦州的狀況是很有趣的。 – 2011-06-17 08:05:38

回答

2

使用system的替代方法是特定於OS的API調用,如statvfs

但我同意奇怪它需要這麼長時間。你可以重新創建嗎?

+0

謝謝我會給statvfs一個去。我的測試運行了幾個小時,我只看過它一次,因此重新創建它並不容易。但我會嘗試這樣做。 – fwgx 2011-06-17 08:34:49

0

也許你可以嘗試使用fstatvfs()/statvfs()系統調用來獲得可用磁盤空間量,並查看是否有任何區別。

1

我已經看到'df'在某些NFS fs掛載時掛起,但客戶端無法訪問服務器。那麼你有沒有安裝網絡fs?在任何情況下,正如其他人已經指出的那樣,您應該使用statvfs()/ fstatvfs()而不是system()。如果掛起的fs不是您想要運行statvfs()的那個,那麼這也可能有助於掛起。

+0

服務器安裝了NFS掛載程序,但它們並未在此記錄過程中或由'df'命令使用。也許如果他們壞了,'df'確實掛斷了。我會給statvfs()一個去看看是否改善了事情。乾杯。 – fwgx 2011-06-17 08:51:36

+0

是的,如果任何掛載的fs掛起,df會掛起,因爲df基本上會做的是爲每個掛載的fs運行statvfs()。 – janneb 2011-06-17 09:33:04