浏览代码

BUG: Fix parsing of linux 2.6 /proc/meminfo format

Previously KWSys SystemInformation parsed this file assuming a strict
order and set of fields, but the order is not reliable.  This
generalizes the implementation to support any order and extra fields.
Brad King 16 年之前
父节点
当前提交
ae284cc5c8
共有 1 个文件被更改,包括 23 次插入47 次删除
  1. 23 47
      Source/kwsys/SystemInformation.cxx

+ 23 - 47
Source/kwsys/SystemInformation.cxx

@@ -2288,7 +2288,7 @@ int SystemInformationImplementation::QueryMemory()
   unsigned long av=0;
   unsigned long ap=0;
   
-  char buffer[1024]; // for skipping unused lines
+  char buffer[1024]; // for reading lines
   
   int linuxMajor = 0;
   int linuxMinor = 0;
@@ -2331,56 +2331,32 @@ int SystemInformationImplementation::QueryMemory()
     // new /proc/meminfo format since kernel 2.6.x
     // Rigorously, this test should check from the developping version 2.5.x
     // that introduced the new format...
-    
-    unsigned long freeMem;
-    unsigned long buffersMem;
-    unsigned long cachedMem;
 
-    int status;
-    
-    status=fscanf(fd,"MemTotal:%lu kB\n", &this->TotalPhysicalMemory);
-    if(status==1)
-      {
-      status+=fscanf(fd,"MemFree:%lu kB\n", &freeMem);
-      }
-    if(status==2)
+    enum { mMemTotal, mMemFree, mBuffers, mCached, mSwapTotal, mSwapFree };
+    const char* format[6] =
+      { "MemTotal:%lu kB", "MemFree:%lu kB", "Buffers:%lu kB",
+        "Cached:%lu kB", "SwapTotal:%lu kB", "SwapFree:%lu kB" };
+    bool have[6] = { false, false, false, false, false, false };
+    unsigned long value[6];
+    int count = 0;
+    while(fgets(buffer, sizeof(buffer), fd))
       {
-      status+=fscanf(fd,"Buffers:%lu kB\n", &buffersMem);
-      }
-    if(status==3)
-      {
-      status+=fscanf(fd,"Cached:%lu kB\n", &cachedMem);
-      }
-    if(status==4)
-      {
-      this->TotalPhysicalMemory /= 1024;
-      this->AvailablePhysicalMemory = freeMem+cachedMem+buffersMem;
-      this->AvailablePhysicalMemory /= 1024;
-      }
-    
-    // Skip SwapCached, Active, Inactive, HighTotal, HighFree, LowTotal
-    // and LowFree.
-    int i=0;
-    bool success=status==4;
-    while(i<7 && success)
-      {
-      char *r=fgets(buffer, sizeof(buffer), fd); // skip a line
-      success=r==buffer;
-      ++i;
-      }
-    
-    if(success)
-      {
-      status+=fscanf(fd,"SwapTotal:%lu kB\n", &this->TotalVirtualMemory);
-      }
-    if(status==5)
-      {
-      status+=fscanf(fd,"SwapFree:%lu kB\n", &this->AvailableVirtualMemory);
+      for(int i=0; i < 6; ++i)
+        {
+        if(!have[i] && sscanf(buffer, format[i], &value[i]) == 1)
+          {
+          have[i] = true;
+          ++count;
+          }
+        }
       }
-    if(status==6)
+    if(count == 6)
       {
-      this->TotalVirtualMemory /= 1024;
-      this->AvailableVirtualMemory /= 1024;
+      this->TotalPhysicalMemory = value[mMemTotal] / 1024;
+      this->AvailablePhysicalMemory =
+        (value[mMemFree] + value[mBuffers] + value[mCached]) / 1024;
+      this->TotalVirtualMemory = value[mSwapTotal] / 1024;
+      this->AvailableVirtualMemory = value[mSwapFree] / 1024;
       }
     else
       {