File indexing completed on 2024-12-22 04:17:23
0001 // Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com 0002 // Copyright 1998-2003 Albert Cahalan <albert@users.sf.net> 0003 // 0004 // This file is placed under the conditions of the GNU Library 0005 // General Public License, version 2, or any later version. 0006 // See file COPYING for information on distribution conditions. 0007 // 0008 // File for parsing top-level /proc entities. 0009 0010 // This file is from the procps project at http://procps.sourceforge.net/ 0011 0012 #include <config.h> 0013 0014 #include <stdio.h> 0015 #include <stdlib.h> 0016 #include <string.h> 0017 #include <ctype.h> 0018 #include <locale.h> 0019 0020 #include <unistd.h> 0021 #include <fcntl.h> 0022 0023 0024 #define BAD_OPEN_MESSAGE \ 0025 "Error: /proc must be mounted\n" \ 0026 " To mount /proc at boot you need an /etc/fstab line like:\n" \ 0027 " /proc /proc proc defaults\n" \ 0028 " In the meantime, mount /proc /proc -t proc\n" 0029 0030 #define MEMINFO_FILE "/proc/meminfo" 0031 static int meminfo_fd = -1; 0032 0033 static char buf[1024]; 0034 0035 /* This macro opens filename only if necessary and seeks to 0 so 0036 * that successive calls to the functions are more efficient. 0037 * It also reads the current contents of the file into the global buf. 0038 */ 0039 #define FILE_TO_BUF(filename, fd) do{ \ 0040 static int local_n; \ 0041 if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) { \ 0042 fprintf(stderr, BAD_OPEN_MESSAGE); \ 0043 fflush(NULL); \ 0044 _exit(102); \ 0045 } \ 0046 lseek(fd, 0L, SEEK_SET); \ 0047 if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \ 0048 perror(filename); \ 0049 fflush(NULL); \ 0050 _exit(103); \ 0051 } \ 0052 buf[local_n] = '\0'; \ 0053 }while(0) 0054 0055 /* evals 'x' twice */ 0056 #define SET_IF_DESIRED(x,y) do{ if(x) *(x) = (y); }while(0) 0057 0058 /***********************************************************************/ 0059 /* 0060 * Copyright 1999 by Albert Cahalan; all rights reserved. 0061 * This file may be used subject to the terms and conditions of the 0062 * GNU Library General Public License Version 2, or any later version 0063 * at your option, as published by the Free Software Foundation. 0064 * This program is distributed in the hope that it will be useful, 0065 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0066 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0067 * GNU Library General Public License for more details. 0068 */ 0069 0070 typedef struct mem_table_struct { 0071 const char *name; /* memory type name */ 0072 unsigned long *slot; /* slot in return struct */ 0073 } mem_table_struct; 0074 0075 static int compare_mem_table_structs(const void *a, const void *b){ 0076 return strcmp(((const mem_table_struct*)a)->name,((const mem_table_struct*)b)->name); 0077 } 0078 0079 /* example data, following junk, with comments added: 0080 * 0081 * MemTotal: 61768 kB old 0082 * MemFree: 1436 kB old 0083 * MemShared: 0 kB old (now always zero; not calculated) 0084 * Buffers: 1312 kB old 0085 * Cached: 20932 kB old 0086 * Active: 12464 kB new 0087 * Inact_dirty: 7772 kB new 0088 * Inact_clean: 2008 kB new 0089 * Inact_target: 0 kB new 0090 * Inact_laundry: 0 kB new, and might be missing too 0091 * HighTotal: 0 kB 0092 * HighFree: 0 kB 0093 * LowTotal: 61768 kB 0094 * LowFree: 1436 kB 0095 * SwapTotal: 122580 kB old 0096 * SwapFree: 60352 kB old 0097 * Inactive: 20420 kB 2.5.41+ 0098 * Dirty: 0 kB 2.5.41+ 0099 * Writeback: 0 kB 2.5.41+ 0100 * Mapped: 9792 kB 2.5.41+ 0101 * Slab: 4564 kB 2.5.41+ 0102 * Committed_AS: 8440 kB 2.5.41+ 0103 * PageTables: 304 kB 2.5.41+ 0104 * ReverseMaps: 5738 2.5.41+ 0105 * SwapCached: 0 kB 2.5.??+ 0106 * HugePages_Total: 220 2.5.??+ 0107 * HugePages_Free: 138 2.5.??+ 0108 * Hugepagesize: 4096 kB 2.5.??+ 0109 */ 0110 0111 /* obsolete */ 0112 unsigned long kb_main_shared; 0113 /* old but still kicking -- the important stuff */ 0114 unsigned long kb_main_buffers; 0115 unsigned long kb_main_cached; 0116 unsigned long kb_main_free; 0117 unsigned long kb_main_total; 0118 unsigned long kb_swap_free; 0119 unsigned long kb_swap_total; 0120 /* recently introduced */ 0121 unsigned long kb_high_free; 0122 unsigned long kb_high_total; 0123 unsigned long kb_low_free; 0124 unsigned long kb_low_total; 0125 /* 2.4.xx era */ 0126 unsigned long kb_active; 0127 unsigned long kb_inact_laundry; 0128 unsigned long kb_inact_dirty; 0129 unsigned long kb_inact_clean; 0130 unsigned long kb_inact_target; 0131 unsigned long kb_swap_cached; /* late 2.4 only */ 0132 /* derived values */ 0133 unsigned long kb_swap_used; 0134 unsigned long kb_main_used; 0135 /* 2.5.41+ */ 0136 unsigned long kb_writeback; 0137 unsigned long kb_slab; 0138 unsigned long nr_reversemaps; 0139 unsigned long kb_committed_as; 0140 unsigned long kb_dirty; 0141 unsigned long kb_inactive; 0142 unsigned long kb_mapped; 0143 unsigned long kb_pagetables; 0144 0145 void meminfo(void){ 0146 char namebuf[16]; /* big enough to hold any row name */ 0147 mem_table_struct findme = { namebuf, NULL}; 0148 mem_table_struct *found; 0149 char *head; 0150 char *tail; 0151 static const mem_table_struct mem_table[] = { 0152 {"Active", &kb_active}, 0153 {"Buffers", &kb_main_buffers}, 0154 {"Cached", &kb_main_cached}, 0155 {"Committed_AS", &kb_committed_as}, 0156 {"Dirty", &kb_dirty}, 0157 {"HighFree", &kb_high_free}, 0158 {"HighTotal", &kb_high_total}, 0159 {"Inact_clean", &kb_inact_clean}, 0160 {"Inact_dirty", &kb_inact_dirty}, 0161 {"Inact_laundry",&kb_inact_laundry}, 0162 {"Inact_target", &kb_inact_target}, 0163 {"Inactive", &kb_inactive}, 0164 {"LowFree", &kb_low_free}, 0165 {"LowTotal", &kb_low_total}, 0166 {"Mapped", &kb_mapped}, 0167 {"MemFree", &kb_main_free}, 0168 {"MemShared", &kb_main_shared}, 0169 {"MemTotal", &kb_main_total}, 0170 {"PageTables", &kb_pagetables}, 0171 {"ReverseMaps", &nr_reversemaps}, 0172 {"Slab", &kb_slab}, 0173 {"SwapCached", &kb_swap_cached}, 0174 {"SwapFree", &kb_swap_free}, 0175 {"SwapTotal", &kb_swap_total}, 0176 {"Writeback", &kb_writeback}, 0177 }; 0178 const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct); 0179 0180 FILE_TO_BUF(MEMINFO_FILE,meminfo_fd); 0181 0182 kb_inactive = ~0UL; 0183 0184 head = buf; 0185 for(;;){ 0186 tail = strchr(head, ':'); 0187 if(!tail) break; 0188 *tail = '\0'; 0189 if(strlen(head) >= sizeof(namebuf)){ 0190 head = tail+1; 0191 goto nextline; 0192 } 0193 strcpy(namebuf,head); 0194 found = bsearch(&findme, mem_table, mem_table_count, 0195 sizeof(mem_table_struct), compare_mem_table_structs 0196 ); 0197 head = tail+1; 0198 if(!found) goto nextline; 0199 *(found->slot) = strtoul(head,&tail,10); 0200 nextline: 0201 tail = strchr(head, '\n'); 0202 if(!tail) break; 0203 head = tail+1; 0204 } 0205 if(!kb_low_total){ /* low==main except with large-memory support */ 0206 kb_low_total = kb_main_total; 0207 kb_low_free = kb_main_free; 0208 } 0209 if(kb_inactive==~0UL){ 0210 kb_inactive = kb_inact_dirty + kb_inact_clean + kb_inact_laundry; 0211 } 0212 kb_swap_used = kb_swap_total - kb_swap_free; 0213 kb_main_used = kb_main_total - kb_main_free; 0214 }