]> granicus.if.org Git - procps-ng/commitdiff
library: exploit linux-4.5 resident memory enhancement
authorJim Warner <james.warner@comcast.net>
Wed, 13 Apr 2016 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@enc.com.au>
Thu, 14 Apr 2016 11:03:03 +0000 (21:03 +1000)
Beginning with linux-4.5, the following new fields are
being added under that /proc/<pid>/status pseudo file:
 . RssAnon - size of resident anonymous memory
 . RssFile - size of resident file mappings
 . RssShmem - size of resident shared memory

This patch just represents the initial library and top
support, sharing a commit message with 2 more patches.

p.s. locked resident memory support was also added but
isn't directly related to the kernel 4.5 enhancements.

Reference(s):
commit 1f8e41d01966ef337bc252bffb181d0acc0c8751
Signed-off-by: Jim Warner <james.warner@comcast.net>
proc/pids.c
proc/pids.h
proc/readproc.c
proc/readproc.h

index aa5879873b1128588fb513cc04852c786d8853ef..19a142e7f451d99ea3c150d08eaffc7dc8c6d314 100644 (file)
@@ -242,6 +242,10 @@ REG_set(VM_EXE,           ul_int,  vm_exe)
 REG_set(VM_LIB,           ul_int,  vm_lib)
 REG_set(VM_LOCK,          ul_int,  vm_lock)
 REG_set(VM_RSS,           ul_int,  vm_rss)
+REG_set(VM_RSS_ANON,      ul_int,  vm_rss_anon)
+REG_set(VM_RSS_FILE,      ul_int,  vm_rss_file)
+REG_set(VM_RSS_LOCKED,    ul_int,  vm_lock)
+REG_set(VM_RSS_SHARED,    ul_int,  vm_rss_shared)
 REG_set(VM_SIZE,          ul_int,  vm_size)
 REG_set(VM_STACK,         ul_int,  vm_stack)
 REG_set(VM_SWAP,          ul_int,  vm_swap)
@@ -493,6 +497,10 @@ static struct {
     { RS(VM_LIB),            f_status,   NULL,      QS(ul_int),   0,        -1            },
     { RS(VM_LOCK),           f_status,   NULL,      QS(ul_int),   0,        -1            },
     { RS(VM_RSS),            f_status,   NULL,      QS(ul_int),   0,        -1            },
+    { RS(VM_RSS_ANON),       f_status,   NULL,      QS(ul_int),   0,        -1            },
+    { RS(VM_RSS_FILE),       f_status,   NULL,      QS(ul_int),   0,        -1            },
+    { RS(VM_RSS_LOCKED),     f_status,   NULL,      QS(ul_int),   0,        -1            },
+    { RS(VM_RSS_SHARED),     f_status,   NULL,      QS(ul_int),   0,        -1            },
     { RS(VM_SIZE),           f_status,   NULL,      QS(ul_int),   0,        -1            },
     { RS(VM_STACK),          f_status,   NULL,      QS(ul_int),   0,        -1            },
     { RS(VM_SWAP),           f_status,   NULL,      QS(ul_int),   0,        -1            },
index f32e1031ca752efcd3f7772b91d7c77990612b27..630e9e86205a2db5e0c292bd3de8246179ebc73d 100644 (file)
@@ -132,6 +132,10 @@ enum pids_item {
     PROCPS_PIDS_VM_LIB,                // ul_int
     PROCPS_PIDS_VM_LOCK,               // ul_int
     PROCPS_PIDS_VM_RSS,                // ul_int
+    PROCPS_PIDS_VM_RSS_ANON,           // ul_int
+    PROCPS_PIDS_VM_RSS_FILE,           // ul_int
+    PROCPS_PIDS_VM_RSS_LOCKED,         // ul_int
+    PROCPS_PIDS_VM_RSS_SHARED,         // ul_int
     PROCPS_PIDS_VM_SIZE,               // ul_int
     PROCPS_PIDS_VM_STACK,              // ul_int
     PROCPS_PIDS_VM_SWAP,               // ul_int
index 0d2eb7cb30e3122a45716b9be335741697ad05a3..380047f222265d5fd8b2e033f553b51c077fde44 100644 (file)
@@ -113,7 +113,7 @@ static inline void free_acquired (proc_t *p, int reuse) {
 ///////////////////////////////////////////////////////////////////////////
 
 typedef struct status_table_struct {
-    unsigned char name[7];        // /proc/*/status field name
+    unsigned char name[8];        // /proc/*/status field name
     unsigned char len;            // name length
 #ifdef LABEL_OFFSET
     long offset;                  // jump address offset
@@ -129,8 +129,11 @@ typedef struct status_table_struct {
 #endif
 #define NUL  {"", 0, 0},
 
+#define GPERF_TABLE_SIZE 128
+
 // Derived from:
 // gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c <if-not-piped>
+// ( --key-positions verified by omission & reported "Computed positions" )
 //
 // Suggested method:
 // Grep this file for "case_", then strip those down to the name.
@@ -144,8 +147,8 @@ typedef struct status_table_struct {
 // the F macro and replacing empty strings with the NUL define.
 //
 // In the status_table_struct watch out for name size (grrr, expanding)
-// and the number of entries (we mask with 63 for now). The table
-// must be padded out to 64 entries, maybe 128 in the future.
+// and the number of entries. Currently, the table is padded to 128
+// entries and we therefore mask with 127.
 
 static void status2proc(char *S, proc_t *restrict P, int is_proc){
     long Threads = 0;
@@ -155,78 +158,76 @@ static void status2proc(char *S, proc_t *restrict P, int is_proc){
   // 128 entries because we trust the kernel to use ASCII names
   static const unsigned char asso[] =
     {
-      64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-      64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-      64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-      64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-      64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-      64, 64, 64, 64, 64, 64, 64, 64, 28, 64,
-      64, 64, 64, 64, 64, 64,  8, 25, 23, 25,
-       6, 25,  0,  3, 64, 64,  3, 64, 25, 64,
-      20,  1,  1,  5,  0, 30,  0,  0, 64, 64,
-      64, 64, 64, 64, 64, 64, 64,  3, 64,  0,
-       0, 18, 64, 10, 64, 10, 64, 64, 64, 20,
-      64, 20,  0, 64, 25, 64,  3, 15, 64,  0,
-      30, 64, 64, 64, 64, 64, 64, 64
+      101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+      101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+      101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+      101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+      101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+      101, 101, 101, 101, 101, 101, 101, 101,   6, 101,
+      101, 101, 101, 101, 101,  45,  55,  25,  31,  50,
+       50,  10,   0,  35, 101, 101,  21, 101,  30, 101,
+       20,  36,   0,   5,   0,  40,   0,   0, 101, 101,
+      101, 101, 101, 101, 101, 101, 101,  30, 101,  15,
+        0,   1, 101,  10, 101,  10, 101, 101, 101,  25,
+      101,  40,   0, 101,   0,  50,   6,  40, 101,   1,
+       35, 101, 101, 101, 101, 101, 101, 101
     };
 
-    static const status_table_struct table[] = {
+    static const status_table_struct table[GPERF_TABLE_SIZE] = {
       F(VmHWM)
-      NUL NUL
-      F(VmLck)
-      NUL
-      F(VmSwap)
+      F(Threads)
+      NUL NUL NUL
       F(VmRSS)
-      NUL
-      F(VmStk)
-      NUL
+      F(VmSwap)
+      NUL NUL NUL
       F(Tgid)
-      F(State)
-      NUL
-      F(VmLib)
-      NUL
+      F(VmStk)
+      NUL NUL NUL
       F(VmSize)
-      F(SigQ)
-      NUL
-      F(SigIgn)
-      NUL
+      F(Gid)
+      NUL NUL NUL
       F(VmPTE)
-      F(FDSize)
-      NUL
-      F(SigBlk)
-      NUL
+      F(VmPeak)
+      NUL NUL NUL
       F(ShdPnd)
-      F(VmData)
-      NUL
-      F(CapInh)
-      NUL
+      F(Pid)
+      NUL NUL NUL
       F(PPid)
-      NUL NUL
-      F(CapBnd)
-      NUL
+      F(VmLib)
+      NUL NUL NUL
       F(SigPnd)
-      NUL NUL
-      F(VmPeak)
-      NUL
+      F(VmLck)
+      NUL NUL NUL
       F(SigCgt)
-      NUL NUL
-      F(Threads)
-      NUL
+      F(State)
+      NUL NUL NUL
       F(CapPrm)
-      NUL NUL
-      F(Pid)
-      NUL
+      F(Uid)
+      NUL NUL NUL
+      F(SigIgn)
+      F(SigQ)
+      NUL NUL NUL
+      F(RssShmem)
+      F(Name)
+      NUL NUL NUL
+      F(CapInh)
+      F(VmData)
+      NUL NUL NUL
+      F(FDSize)
+      NUL NUL NUL NUL
+      F(SigBlk)
+      NUL NUL NUL NUL
       F(CapEff)
-      NUL NUL
-      F(Gid)
-      NUL
+      NUL NUL NUL NUL
+      F(CapBnd)
+      NUL NUL NUL NUL
       F(VmExe)
-      NUL NUL
-      F(Uid)
-      NUL
+      NUL NUL NUL NUL
       F(Groups)
-      NUL NUL
-      F(Name)
+      NUL NUL NUL NUL
+      F(RssAnon)
+      NUL NUL NUL NUL
+      F(RssFile)
     };
 
 #undef F
@@ -248,7 +249,7 @@ ENTER(0x220);
         // examine a field name (hash and compare)
     base:
         if(unlikely(!*S)) break;
-        entry = table[63 & (asso[(int)S[3]] + asso[(int)S[2]] + asso[(int)S[0]])];
+        entry = table[(GPERF_TABLE_SIZE -1) & (asso[(int)S[3]] + asso[(int)S[2]] + asso[(int)S[0]])];
         colon = strchr(S, ':');
         if(unlikely(!colon)) break;
         if(unlikely(colon[1]!='\t')) break;
@@ -364,6 +365,15 @@ ENTER(0x220);
     case_VmRSS:
         P->vm_rss = strtol(S,&S,10);
         continue;
+    case_RssAnon:       // subset of VmRSS, linux-4.5
+        P->vm_rss_anon = strtol(S,&S,10);
+        continue;
+    case_RssFile:       // subset of VmRSS, linux-4.5
+        P->vm_rss_file = strtol(S,&S,10);
+        continue;
+    case_RssShmem:      // subset of VmRSS, linux-4.5
+        P->vm_rss_shared = strtol(S,&S,10);
+        continue;
     case_VmSize:
         P->vm_size = strtol(S,&S,10);
         continue;
@@ -439,6 +449,7 @@ ENTER(0x220);
 
 LEAVE(0x220);
 }
+#undef GPERF_TABLE_SIZE
 
 static void supgrps_from_supgids (proc_t *p) {
     char *g, *s;
index 809247160a8698da1bbdbb60d843da10458f74d5..10160b40a5989825e60567f70b673badd7fbbe41 100644 (file)
@@ -117,6 +117,9 @@ typedef struct proc_t {
        vm_size,        // status          equals 'size' (as kb)
        vm_lock,        // status          locked pages (as kb)
        vm_rss,         // status          equals 'rss' and/or 'resident' (as kb)
+       vm_rss_anon,    // status          the 'anonymous' portion of vm_rss (as kb)
+       vm_rss_file,    // status          the 'file-backed' portion of vm_rss (as kb)
+       vm_rss_shared,  // status          the 'shared' portion of vm_rss (as kb)
        vm_data,        // status          data only size (as kb)
        vm_stack,       // status          stack only size (as kb)
        vm_swap,        // status          based on linux-2.6.34 "swap ents" (as kb)