Thread: Reading /proc/stat and passing file to func

  1. #1
    Registered User
    Join Date
    Feb 2019
    Posts
    12

    Reading /proc/stat and passing file to func

    I am trying to pass a file to a function. The file is /proc/stat, and the CPU portion works fine. This is just a small part of another file, broken down for help. It is run every second, and I'd prefer not to open/close the file every second, hence opening it once and passing to the function.

    The issue is that when the file is passed to the function, it only grabs the info once and displays the correct CPU. It gives no result thereafter. If the file is opened within the function, it works fine.


    cpu.cpp:
    Code:
    /*
    
      g++ -std=c++17 -Ofast -Wall cpu.cpp -o cpu -lpthread -lX11
    
    */
    
    #include <sstream>
    #include<fstream>
    #include<iostream>
    #include<string>
    #include<chrono>
    #include<thread>
    #include"sys/sysinfo.h"
    #include<sys/types.h>
    #include<ctime>
    #include<sys/ioctl.h> 
    #include<sys/socket.h> /* socket() */
    #include<arpa/inet.h>  
    #include<cstdlib>
    #include<cstdio>
    #include<unistd.h>     /* close()  */
    #include<linux/if.h>   /* struct ifreq */
    #include<cstring>     
    #include<X11/Xlib.h>
    
    using namespace std;
    
    std::string cpuPercent(FILE *file)
    {
         
        static unsigned int lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;
        float percent;
        short intPercent;
        std::string s;
         
        //rewind(file);
        fseek(file, 0L, SEEK_SET);
    
    
        if (fseek(file, 0L, SEEK_SET) != 0 )
            std::cout << "Didn't reset properly!" << std::endl;
    
    
        unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;
    
        fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow, &totalSys, &totalIdle);
    
        if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow ||
            totalSys < lastTotalSys || totalIdle < lastTotalIdle)
        {
            //Overflow detection. Just skip this value.
            percent = -1.0;
        }else{
            total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) + (totalSys - lastTotalSys);
            percent = total * 100;
            total += (totalIdle - lastTotalIdle);
            percent /= total;
        }
         
        lastTotalUser    = totalUser;
        lastTotalUserLow = totalUserLow;
        lastTotalSys     = totalSys;
        lastTotalIdle    = totalIdle;
     
        intPercent = percent;
        s = to_string(intPercent);
         
        return s + "% ";
    }
    
    
    std::string cpuPercent2()
    {
        FILE* file2 = fopen("/proc/stat", "r");
         
        static unsigned int lastTotalUser2, lastTotalUserLow2, lastTotalSys2, lastTotalIdle2;
        float percent;
        short intPercent;
        std::string s;
         
        rewind(file2);
        fseek(file2, 0L, SEEK_SET);
        if (fseek(file2, 0L, SEEK_SET) != 0 ) {
            std::cout << "Didn't reset properly!" << std::endl;
        }
    
        unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;
    
        fscanf(file2, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow, &totalSys, &totalIdle);
    
    
        if (totalUser < lastTotalUser2 || totalUserLow < lastTotalUserLow2 ||
            totalSys < lastTotalSys2 || totalIdle < lastTotalIdle2)
        {
            //Overflow detection. Just skip this value.
            percent = -1.0;
        }else{
            total = (totalUser - lastTotalUser2) + (totalUserLow - lastTotalUserLow2) + (totalSys - lastTotalSys2);
            percent = total * 100;
            total += (totalIdle - lastTotalIdle2);
            percent /= total;
        }
         
        lastTotalUser2    = totalUser;
        lastTotalUserLow2 = totalUserLow;
        lastTotalSys2     = totalSys;
        lastTotalIdle2    = totalIdle;
     
        intPercent = percent;
        s = to_string(intPercent);
        
        fclose(file2);
    
        return s + "% ";
    }
        
    int main(int argc, char* argv[])
    {
        FILE* file = fopen("/proc/stat", "r");
    
        while(1)
        {
           std::cout << "Cpu (file passed to func): " << cpuPercent(file) << std::endl; 
           std::cout << "Cpu (file within func): " << cpuPercent2() << std::endl; 
    
           sleep(1);
        }
    
        fclose(file);
    
        return 0;
    }

    Here is a side-by-side of the results printed out:
    Code:
    Cpu (file passed to func): 4% Cpu (file within func): 4% 
    Cpu (file passed to func): 0% 
    Cpu (file within func): 11% 
    Cpu (file passed to func): 0% 
    Cpu (file within func): 15% 
    Cpu (file passed to func): 0% 
    Cpu (file within func): 17% 
    Cpu (file passed to func): 0%
    The file that is passed to the function only gives the first result. I suspect that it is either not reading /proc/stat properly or it is not resetting. The second file works fine.

    Any ideas?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,490
    proc(5) - Linux manual page

    The whole of /proc is a pseudo file system.

    The data you see is a snapshot of the system state at a moment in time, and that moment is when you open the file.

    If it were continuous live data, you would need to take precautions.
    cpu 59880 158 14415 2612974 5069 0 77 0 0 0
    cpu 60010 158 14416 2613640 5070 0 77 0 0 0


    Imagine you'd got as far a parsing "cpu 5" when the OS rewrote the data as 60010.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. /proc/pid/mem Reading
    By redcrusher in forum C Programming
    Replies: 1
    Last Post: 01-14-2012, 11:38 AM
  2. Reading a proc file in user space
    By Fillis52 in forum C Programming
    Replies: 3
    Last Post: 12-06-2010, 11:03 AM
  3. Reading /proc
    By crisis in forum Linux Programming
    Replies: 3
    Last Post: 11-07-2007, 04:46 AM
  4. /proc/stat
    By scrapedbr in forum Linux Programming
    Replies: 2
    Last Post: 06-24-2004, 04:38 PM
  5. Passing Array 2 Func...
    By NickESP in forum C++ Programming
    Replies: 3
    Last Post: 02-06-2003, 05:54 PM

Tags for this Thread