读/ sys / block / $ DEVICE / stat会导致竞争状况吗?

时间:2017-07-21 17:02:57

标签: c++ linux race-condition

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

替换先前保存的值,然后保存当前值。所以我知道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_);
    
    }
    

2 个答案:

答案 0 :(得分: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;

}

答案 1 :(得分:0)

我已复制此问题,并报告bug