【问题标题】:Can reading /sys/block/$DEVICE/stat cause race condition?读取 /sys/block/$DEVICE/stat 会导致竞争状况吗?
【发布时间】:2017-07-21 17:02:56
【问题描述】:

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

减去以前保存的值,然后保存当前值。所以我知道硬盘活动。 但有时我的值太大(在最后和当前之间)(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_);
    
    }
    

【问题讨论】:

  • 关于 (1) - 内核不写入此文件(或实际上/proc/sys 等中的任何文件)。相反,它会在读取文件时按需生成文件的明显内容。因此,正在写入的文件和正在读取的文件之间不会存在竞争条件。但是,为了生成输出而读取的某些内部内核数据结构可能不会完全以原子方式更新。如果是这样的话,内核开发人员可能有兴趣了解它......
  • 它在 6 - 7 天内发生一次,所以我写了一个小程序 (C++),它每毫秒读取这个文件,我还运行了一个 bash 脚本来做同样的事情。试图复制。

标签: c++ linux race-condition


【解决方案1】:

完整列表

#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;

}

【讨论】:

    【解决方案2】:

    我已经转载了这个问题,并报告了bug

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 2014-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-16
      • 1970-01-01
      相关资源
      最近更新 更多