2017-07-21 84 views
0

每一秒鐘,我的程序讀取/ sys/block/$ DEVICE/stat。

Substractes先前保存的值,然後保存當前值。所以我知道hdd活動。 但是有時候我的值太大(在最後和當前之間)(5GB /秒)。

  1. 它可以在比賽條件(如果在應用程序讀取它同時內核寫入文件 )?
  2. 是否存在任何標準解決方案來避免這種情況?

    const int HDD_READ_POS  = 2; 
    const int HDD_WRITE_POS = 6; 
    const int UNIX_SECTOR_SIZE = 512; 
    
    std::tuple<uint64_t, uint64_t> hddStatus(const std::string &name) 
    { 
        std::ifstream in("/sys/block/"+name+"/stat"); 
    
        auto readVal_ = static_cast<uint64_t>(0); 
        auto writeVal_= static_cast<uint64_t>(0); 
    
        if (! in.is_open()) { 
         return std::tuple<uint64_t, uint64_t> (readVal_, writeVal_); 
        } 
    
        std::string line; 
        std::regex rgx ("\\d+"); 
        std::regex_token_iterator<std::string::iterator> end; 
    
        while (std::getline(in, line)){ 
    
         std::regex_token_iterator<std::string::iterator> iter(line.begin(), line.end(), rgx, 0); 
         int pos_ = 0 ; 
    
         while (iter != end) { 
    
          if (pos_ == HDD_READ_POS){ 
           readVal_ = std::stoul(*iter) ; 
          } 
    
          if (pos_ == HDD_WRITE_POS){ 
           writeVal_ = std::stoul(*iter) ; 
          } 
    
          ++iter; 
          ++pos_; 
         } 
        } 
    
        return std::tuple<uint64_t, uint64_t> (readVal_, writeVal_); 
    
    } 
    
+0

關於(1) - 內核不寫入到該文件(或事實上'/ proc','/ sys'等中的任何文件)。相反,它在讀取時按需生成文件的明顯內容。所以在寫入文件和讀取文件之間不會存在競爭條件。但是,爲了生成輸出而讀取的某些內部內核數據結構可能不會完全以原子方式更新。如果是這樣的話,內核開發人員可能有興趣瞭解它... – twalberg

+0

它發生在6-7天的一次,所以我寫了一個小程序(C++),它每毫秒讀取一個文件,也是我跑了一個bash腳本來做同樣的事情。試圖重現。 – Sergey

回答

0

全部列表

#include <iostream> 
#include <fstream> 
#include <regex> 
#include <tuple> 
#include <chrono> 
#include <thread> 
#include <cstdint> 

const int HDD_READ_POS  = 2; 
const int HDD_WRITE_POS = 6; 
const int UNIX_SECTOR_SIZE = 512; 
uint64_t prevRead = static_cast<uint64_t>(0); 
uint64_t prevWrite = static_cast<uint64_t>(0); 

std::tuple<uint64_t, uint64_t> hddStatus(const std::string &name="sda"){ 
    std::ifstream in("/sys/block/"+name+"/stat"); 

auto readVal_ = static_cast<uint64_t>(0); 
auto writeVal_= static_cast<uint64_t>(0); 

if (! in.is_open()) { 
    return std::tuple<uint64_t, uint64_t> (readVal_, writeVal_); 
} 

std::string line; 
std::regex rgx ("\\d+"); 
std::regex_token_iterator<std::string::iterator> end; 

while (std::getline(in, line)){ 

    std::regex_token_iterator<std::string::iterator> iter(line.begin(), line.end(), rgx, 0); 
    int pos_ = 0 ; 

    while (iter != end) { 

     if (pos_ == HDD_READ_POS){ 
      readVal_ = std::stoul(*iter) ; 
     } 

     if (pos_ == HDD_WRITE_POS){ 
      writeVal_ = std::stoul(*iter) ; 
     } 

     ++iter; 
     ++pos_; 
    } 
} 

return std::tuple<uint64_t, uint64_t> (readVal_, writeVal_); 

} 


void init() 
{ 

    auto values = hddStatus(); 
    prevRead = std::get<0>(values) * UNIX_SECTOR_SIZE; 
    prevWrite = std::get<1>(values) * UNIX_SECTOR_SIZE; 
} 

int main(int argc, char const *argv[]) 
{ 
init(); 


while(true){ 

std::ofstream stat("statistics.txt", std::fstream::out | std::fstream::app); 
if (stat.is_open()){  

     auto values = hddStatus(); 
     auto read = std::get<0>(values) * UNIX_SECTOR_SIZE; 
     auto write = std::get<1>(values) * UNIX_SECTOR_SIZE; 

     // stat<<"Current Read: "<< read<<" Write: "<<write<<'\n'; 
     if (read > prevRead){ 
      stat<<"Diff Read: "<< read - prevRead <<'\n'; 
      std::cout<<"Diff Read: "<< read - prevRead <<'\n'; 
     } 

     if (write > prevWrite){ 
      stat<<"Diff Write: "<<write - prevWrite <<'\n'; 
      std::cout<<"Diff Write: "<<write - prevWrite <<'\n'; 
     } 

     prevRead = read; 
     prevWrite = write; 

     std::this_thread::sleep_for(std::chrono::milliseconds(1)); 

    } 
} 

return 0; 

}