1

I've written a little tool to grep inside the adddress space of a proces with a start and end delimiter in ECMAScript regex syntax. I'm parsing /proc/pid/maps twice to determine the largest mapping first. So if I've opened this mapping description first and rewind it with a seek( 0 ) do I still get the same data, i.e. is this file a snapshot with unlimited repeatable readability ?

4
  • Please add details, e.g. show a sample of what your are matching AND the regular expression you are using as code blocks. Commented Feb 6 at 19:12
  • I'm not asking for the regex but if the second read of the /proc/pid/maps is repeatable, i.e. delivers identical results. Commented Feb 6 at 19:58
  • I'm not sure I understand ... /proc, in general, is a pseudo filesystem that gives you a view into the current kernel. If the running executable matching the pid didn't change neither should its memory allocation? Commented Feb 6 at 21:46
  • I asked whether I open /proc/pid/maps, read it and rewind the file pointer to zero I get still the same data, no matter how much timed passed, i.e. this is a snapshot of the time where I opened the file. Or If I get updated data when I keep the file opened and re-read it. Commented Feb 7 at 9:38

1 Answer 1

0

I wrote a little C++20 program that scans the address ranges of the process and logs its ranges, then makes an mmap() for 64kiB of memory and then looks if the ranges on the same opened file are still the same. They're not ! So /proc/pid/maps isn't a repeatable snapshot.

#include <iostream>
#include <regex>
#include <fstream>
#include <charconv>
#include <sstream>
#include <array>
#include <unistd.h>
#include <sys/mman.h>

using namespace std;

int main( int argc, char **argv )
{
    int pid = getpid();
    ostringstream oss;
    oss << "/proc/" << pid << "/maps";
    ifstream ifs( oss.str() );
    using range_t = pair<size_t, size_t>;
    static regex rxAddrsAndRd( "^([0-9a-f]{1,16})-([0-9a-f]{1,16}) *[rR]", regex_constants::ECMAScript | regex_constants::icase );
    match_results<string::iterator> mr;
    auto parse = [&]( auto fn )
        requires requires() { fn( range_t() ); }
    {
        ifs.clear();
        ifs.seekg( 0 );
        for( string line; getline( ifs, line ); )
        {
            if( !regex_search( line.begin(), line.end(), mr, rxAddrsAndRd ) )
                continue;
            array<size_t, 2> addrs;
            for( size_t a = 0; a <= 1; ++a )
                from_chars( to_address( mr[a + 1].first ), to_address( mr[a + 1].second ), addrs[a] );
            if( !fn( range_t( addrs[0], addrs[1] ) ) )
                return;
        }
    };
    vector<range_t> ranges;
    parse( [&]( range_t range ) { ranges.emplace_back( range ); return true; } );
    if( !mmap( nullptr, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS | MAP_POPULATE, -1, 0 ) )
        return EXIT_FAILURE;
    auto cmp = ranges.begin();
    bool equal = true;
    parse( [&]( range_t range )
        {
            if( cmp != ranges.end() && range == *cmp++ )
                return true;
            equal = false;
            return false;
        } );
    cout << (equal ? "snapshot" : "non-snapshot") << endl;
}
1

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.