From: SL B. <st...@bs...> - 2002-04-25 08:25:09
|
This is a sial implementation of a system memory analysis function. This should work in degraded fashion on Linux 2.2.x systems. Modifier flags -k: Output totals in KiloBytes -m: Output totals in MegaBytes >> mem /* No parameters ~= contents of /proc/meminfo */ >> mem -i /* or -i flag */ total: used: free: buffers: cached: Mem: 268435456 261464064 6971392 8425472 133001216 Swap: 402997248 137838592 265158656 MemTotal: 268435456 B MemFree: 6971392 B Buffers: 8425472 B Cached: 104091648 B SwapCached: 28909568 B Active: 76062720 B Inactive: 153747456 B HighTotal: 0 B HighFree: 0 B LowTotal: 268435456 B LowFree: 6971392 B SwapTotal: 402997248 B SwapFree: 265158656 B Committed AS: 969502720 B >> mem -i -k total: used: free: buffers: cached: Mem: 268435456 261513216 6922240 8425472 133033984 Swap: 402997248 137838592 265158656 MemTotal: 262144 kB MemFree: 6760 kB Buffers: 8228 kB Cached: 101652 kB SwapCached: 28264 kB Active: 74280 kB Inactive: 150188 kB HighTotal: 0 kB HighFree: 0 kB LowTotal: 262144 kB LowFree: 6760 kB SwapTotal: 393552 kB SwapFree: 258944 kB Committed AS: 946792 kB >> mem -z /* map -- list a physical memory map */ Node 0: Zones = 2, start=0x00000000, map_nr=0, size=65536 ====================================== Name Start Size Free Active Inactive Cached DMA 0x0 4096 428 558 2022 1650 Normal 0x1000000 61440 1082 18570 37721 34517 ====================================== >> mem -s /* swap -- list a map of swap usage */ Filename Type Size Used Priority /dev/sda5 partition 822452224 0 -1 /dev/sda6 partition 1069244416 0 -2 /dev/sda7 partition 1332453376 0 -3 /swap1 file 67100672 0 -4 /swap2 file 67100672 0 -5 /swap3 file 67100672 0 -6 /swap4 file 67100672 0 -7 /home/swap/swap1/data file 102391808 0 -8 /home/swap/swap2/data file 153591808 0 -9 /home/swap/swap3/data file 71671808 0 -10 /home/swap/swap4/data file 34123776 0 -11 Total Swap = 3854331904 B, Used = 0 B, Free = 3854331904 B >> mem -sm Filename Type Size Used Priority /dev/sda5 partition 784 0 -1 /dev/sda6 partition 1019 0 -2 /dev/sda7 partition 1270 0 -3 /swap1 file 63 0 -4 /swap2 file 63 0 -5 /swap3 file 63 0 -6 /swap4 file 63 0 -7 /home/swap/swap1/data file 97 0 -8 /home/swap/swap2/data file 146 0 -9 /home/swap/swap3/data file 68 0 -10 /home/swap/swap4/data file 32 0 -11 Total Swap = 3675 MB, Used = 0 MB, Free = 3675 MB mem.sial ---------------------------- Cut Here -------------------------------- /* Copyright(C) 2002 NEC Corporation, All rights reserved This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* mem.sial -- print various statistics about memory usage. */ /* declarations from swap.h */ static int PAGE_SIZE = 0; #define SWP_USED 1 #define SWP_WRITEOK 3 #define SWAP_CLUSTER_MAX 32 #define SWAP_MAP_MAX 0x7fff #define SWAP_MAP_BAD 0x8000 #define MAX_SWAPFILES 32 /* from mmzone.h */ #define ZONE_DMA 0 #define ZONE_NORMAL 1 #define ZONE_HIGHMEM 2 #define MAX_NR_ZONES 3 #define B(n) (n) static unsigned long int K(unsigned int value) { if (kflag) { return value / 1024; } else if (mflag) { return value / 1024 / 1024; } else { return value; } } static string Units() { if (kflag) { return " k"; } else if (mflag) { return " M"; } else { return " "; } } static string swapbannerfmt = "%-32s%-16s%-11s%-11s%s\n"; static string swapdatafmt = "%-32s%-16s%-11lu%-11d%d\n"; void mem_banner_print() { printf(swapbannerfmt, "Filename", "Type", "Size", "Used", "Priority"); } #define IS_ROOT(x) ((x) == (x)->d_parent) string d_path(struct dentry *dentry, struct vfsmount *vfsmnt) { struct dentry *root; struct vfsmount *rootmnt; string retval; struct dentry *parent; rootmnt = *(struct vfsmount **)root_vfsmnt; root = rootmnt->mnt_mountpoint; retval = ""; while (1) { if (dentry == root && vfsmnt == rootmnt) break; if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { /* Global root? */ if (vfsmnt->mnt_parent == vfsmnt) { retval = getnstr(dentry->d_name.name, dentry->d_name.len) + retval; return retval; } dentry = vfsmnt->mnt_mountpoint; vfsmnt = vfsmnt->mnt_parent; continue; } parent = dentry->d_parent; retval = "/" + getnstr(dentry->d_name.name, dentry->d_name.len) + retval; dentry = parent; } return retval; } void mem_swap_print(int num, struct swap_info_struct *swap, unsigned long int used) { string swap_type; string swap_file; if (!swap->swap_device) { swap_type = "file"; } else { swap_type = "partition"; } swap_file = d_path(swap->swap_file, swap->swap_vfsmnt); printf(swapdatafmt, swap_file, swap_type, K((swap->pages) * PAGE_SIZE), K(used * PAGE_SIZE), swap->prio); } void mem_zone_print(int num, struct zone_struct *z) { unsigned long int active = 0, inactive = 0, cache = 0; if (num == 0) { //printf("Zone %d\n", num); printf("======================================\n"); printf("%7s %10s %10s %8s %8s %8s %8s\n", "Name", "Start", "Size", "Free", "Active", "Inactive", "Cached"); } else if (num == -1) { printf("======================================\n"); return; } if (member(z, "nr_active_pages")) { active = z->nr_active_pages; } if (member(z, "nr_inactive_pages")) { inactive = z->nr_inactive_pages; } if (member(z, "nr_cache_pages")) { cache = z->nr_cache_pages; } printf("%-7s %12s %10Lu %8Lu %8Lu %8Lu %8Lu\n", getstr(z->name), sprintf("0x%Lx", z->zone_start_paddr), z->size, z->free_pages, active, inactive, cache); } unsigned int nr_ram_pages(void) { unsigned int sum; struct pglist_data *pgdat = *(struct pglist_data **)pgdat_list; sum = 0; while (pgdat) { sum += pgdat->node_size; pgdat = pgdat->node_next; } return sum; } unsigned int nr_free_pages(void) { unsigned int sum; struct zone_struct *zone; struct pglist_data *pgdat = *(struct pglist_data **)pgdat_list; sum = 0; while (pgdat) { for (zone = pgdat->node_zones; zone < (pgdat->node_zones + MAX_NR_ZONES); zone++) { sum += zone->free_pages; } pgdat = pgdat->node_next; } return sum; } unsigned int nr_high_pages(void) { struct pglist_data *pgdat = *(struct pglist_data **)pgdat_list; unsigned int pages = 0; while (pgdat) { pages += pgdat->node_zones[ZONE_HIGHMEM].size; pgdat = pgdat->node_next; } return pages; } unsigned int nr_free_highpages(void) { struct pglist_data *pgdat = *(struct pglist_data **)pgdat_list; unsigned int pages = 0; while (pgdat) { pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages; pgdat = pgdat->node_next; } return pages; } /* Can't use a struct for this, it doesn't work */ static unsigned long int totalram; static unsigned long int freeram; static unsigned long int bufferram; static unsigned long int totalswap; static unsigned long int freeswap; static unsigned long int procs; static unsigned long int totalhigh; static unsigned long int freehigh; static unsigned long int usedswap; static unsigned long int pg_size; static unsigned long int committed; static unsigned long int active_pages; static unsigned long int inactive_pages; static unsigned long int cached_pages; static unsigned long int swap_pages; void si_meminfo() { totalram = (*(unsigned int *)totalram_pages) * PAGE_SIZE; if (exists("totalhigh_pages")) { totalhigh = (*(unsigned int *)totalhigh_pages) * PAGE_SIZE; } else { totalhigh = 0; } // totalram_pages may be zero in misconfigured Turbolinux kernels if (totalram == 0) { // This won't give the same answer, but it's close totalram = nr_ram_pages() * PAGE_SIZE; totalhigh = nr_high_pages() * PAGE_SIZE; } freeram = nr_free_pages() * PAGE_SIZE; bufferram = (*(unsigned int *)buffermem_pages) * PAGE_SIZE; freehigh = nr_free_highpages() * PAGE_SIZE; return; } void si_swapinfo() { int i, j, total; unsigned long int nr_to_be_unused = 0; struct swap_info_struct *swap; unsigned short *usp; int first = 1; int free_swap = 0, total_swap = 0; int add_total = !exists("total_swap_pages"); if (!exists("swap_info")) { printf("Oops. Can't find `swap_info'\n"); return; } swap = (struct swap_info_struct *)swap_info; for (i = 0; i < *(int *)nr_swapfiles; i++, swap++) { if ((swap->flags & SWP_USED) && (swap->swap_map != 0)) { unsigned long int inuse; usp = swap->swap_map; total = swap->max; for (j = 0, inuse = 0; j < total; j++, usp++) { if (add_total) { // Linux 2.2 switch (*usp) { case SWAP_MAP_BAD: continue; case 0: free_swap++; default: total_swap++; } } else { // Linux 2.4+ switch (*usp) { case 0: case SWAP_MAP_BAD: continue; default: inuse++; break; } } } if ((aflag || sflag) && !add_total) { if (first) { first = 0; mem_banner_print(); } mem_swap_print(i+1, swap, inuse); } nr_to_be_unused += inuse; } } if ((aflag || sflag) && !add_total) { printf("\n"); } if (add_total) { totalswap = total_swap * PAGE_SIZE; freeswap = free_swap * PAGE_SIZE; usedswap = totalswap - freeswap; } else { totalswap = (*((int *)total_swap_pages)) * PAGE_SIZE; freeswap = (*((int *)nr_swap_pages)) * PAGE_SIZE; usedswap = nr_to_be_unused*PAGE_SIZE; } return; } static string lblfmt="%-13s"; static string valfmt="%12Lu"; void proc_meminfo() { struct address_space *Swapper_space; pg_size = ((*(unsigned long *)page_cache_size) * PAGE_SIZE) - bufferram; if (exists("vm_committed_space")) { committed = (*(unsigned long *)vm_committed_space) * PAGE_SIZE; } else { committed = 0; } if (exists("nr_active_pages")) { active_pages = (*(unsigned long *)nr_active_pages) * PAGE_SIZE; } else { // old kernel active_pages = 0; } if (exists("nr_inactive_pages")) { inactive_pages = (*(unsigned long *)nr_inactive_pages) * PAGE_SIZE; } else { inactive_pages = 0; } if (exists("swapper_space")) { Swapper_space = (struct address_space *)swapper_space; cached_pages = pg_size - (Swapper_space->nrpages * PAGE_SIZE); swap_pages = Swapper_space->nrpages * PAGE_SIZE; } printf(" total: used: free:" + " buffers: cached:\n"); printf("Mem: %8Lu %8Lu ", B(totalram), B(totalram-freeram)); printf("%8Lu %8Lu %8Lu\n", B(freeram), B(bufferram), B(pg_size)); printf("Swap: %8Lu %8Lu %8Lu\n", B(totalswap), B(usedswap), B(freeswap)); printf(lblfmt, "MemTotal:"); printf(valfmt+"%sB", K(totalram), Units()); printf("\n"); printf(lblfmt, "MemFree:"); printf(valfmt+"%sB", K(freeram), Units()); printf("\n"); printf(lblfmt, "Buffers:"); printf(valfmt+"%sB", K(bufferram), Units()); printf("\n"); if (exists("swapper_space")) { printf(lblfmt, "Cached:"); printf(valfmt+"%sB", K(cached_pages), Units()); printf("\n"); printf(lblfmt, "SwapCached:"); printf(valfmt+"%sB", K(swap_pages), Units()); printf("\n"); } if (exists("nr_active_pages")) { printf(lblfmt, "Active:"); printf(valfmt+"%sB", K(active_pages), Units()); printf("\n"); } if (exists("nr_inactive_pages")) { printf(lblfmt, "Inactive:"); printf(valfmt+"%sB", K(inactive_pages), Units()); printf("\n"); } if (exists("totalhigh_pages")) { printf(lblfmt, "HighTotal:"); printf(valfmt+"%sB", K(totalhigh), Units()); printf("\n"); printf(lblfmt, "HighFree:"); printf(valfmt+"%sB", K(freehigh), Units()); printf("\n"); } printf(lblfmt, "LowTotal:"); printf(valfmt+"%sB", K(totalram - totalhigh), Units()); printf("\n"); printf(lblfmt, "LowFree:"); printf(valfmt+"%sB", K(freeram - freehigh), Units()); printf("\n"); printf(lblfmt, "SwapTotal:"); printf(valfmt+"%sB", K(totalswap), Units()); printf("\n"); printf(lblfmt, "SwapFree:"); printf(valfmt+"%sB", K(freeswap), Units()); printf("\n"); if (exists("vm_committed_space")) { printf(lblfmt, "Committed AS:"); printf(valfmt+"%sB", K(committed), Units()); printf("\n"); } } void mem() { struct pglist_data *pgdat; struct zone_struct *zone; int i, j; if (PAGE_SIZE == 0) { PAGE_SIZE = getpagesize(); } if (!zflag && !sflag && !aflag && !iflag) { /* noflags, default to /proc/meminfo format */ iflag = 1; } if ((zflag || aflag) && exists("pgdat_list")) { pgdat = *(struct pglist_data **)pgdat_list; for (i = 0; pgdat; i++, pgdat=pgdat->node_next) { printf("Node %d: Zones = %d, start=0x%08x, " + "map_nr=%d, size=%d\n", pgdat->node_id, pgdat->nr_zones, pgdat->node_start_paddr, pgdat->node_start_mapnr, pgdat->node_size); for (j = 0; j < pgdat->nr_zones; j++) { mem_zone_print(j, &pgdat->node_zones[j]); } mem_zone_print(-1, (struct zone_struct *)0); } } si_swapinfo(); if (sflag || aflag) { printf("Total Swap = %lu%sB, Used = %lu%sB, Free = %lu%sB\n", K(totalswap), Units(), K(usedswap), Units(), K(freeswap), Units()); } si_meminfo(); if (aflag) { printf("Total RAM=%lu%sB, Used = %lu%sB, " + "Free=%lu%sB, Buffered=%lu%sB, " + "High=%lu%sB, Free=%lu%sB\n", K(totalram), Units(), K(totalram-freeram), Units(), K(freeram), Units(), K(bufferram), Units(), K(totalhigh), Units(), K(freehigh), Units()); } if (aflag || iflag) { proc_meminfo(); } return; } string mem_help() { return "mem prints out various structures associated with memory\n" + "usage. The default output size is in bytes. If the -k\n" + "flag is given, output is in kilobytes. If the -m flag\n" + "is given, output is in megabytes. There are various\n" + "styles available. -z prints out the zone tables. -s\n" + "prints out the swap device tables. -i prints out\n" + "the information normally found in /proc/meminfo. -a\n" + "prints out everything. If no options are given, -i is\n" + "assumed. Multiple options are permitted.\n\n" + "Note: Not all options are supported on all versions\n" + "of Linux.\n"; } string mem_opt() { return "kmzsai"; } string mem_usage() { return "[-km] [-zsai]"; } |