[aadk-commits] dbailey: uClinux/trunk r536 - /uClinux/trunk/uClinux-dist/user/procwatch/

SVN commits to the AADK repository aadk-commits at lists.digium.com
Fri Jul 20 17:16:55 CDT 2007


Author: dbailey
Date: Fri Jul 20 17:16:54 2007
New Revision: 536

URL: http://svn.digium.com/view/aadk?view=rev&rev=536
Log:
Add ability to use a tunable to force the freeing of unused page cache RAM.  

Modified:
    uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c

Modified: uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c?view=diff&rev=536&r1=535&r2=536
==============================================================================
--- uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c (original)
+++ uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c Fri Jul 20 17:16:54 2007
@@ -22,17 +22,23 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <asm/page.h>
+#include <sys/sysinfo.h>
 #include <linux/version.h>
 #include <linux/watchdog.h>
 
 #define MAX_PROC_NAME_SIZE	256
 #define MAX_PROCESS			32
 #define DEFAULT_SLEEP_VAL 	(2000)
+#define DEFAULT_CACHE_MEMORY_TRIGGER 	(12000)
 
 #define STATUS_LINE_ARG		"Name:"
+
+#define CACHED_MEMORY_ARG		"Cached:"
 		
 /*** Local Prototypes ***/
 static void show_usage(void);
+void try_to_free_cache(int val);
+int memory_in_cache(void);
 
 		
 struct app_monitor {
@@ -53,9 +59,12 @@
 	int				opt;
 	int 			daemon = 0;
 	pid_t 			pid, sid;
-		
+	long 			memory_allocated_in_cache;
+	long			memory_cache_trigger = DEFAULT_CACHE_MEMORY_TRIGGER;
+	struct sysinfo 	sys_info;
+
 	opterr = 0;
-	while ((opt = getopt(argc, argv, "?dp:t:w:")) > 0) {
+	while ((opt = getopt(argc, argv, "?dp:t:w:c:")) > 0) {
 		switch (opt) {
 			case 'p':
 				proc_monitor[num_to_monitor].name 	= optarg;
@@ -75,6 +84,9 @@
 			case 'd':
 				daemon = 1;
 				break;
+			case 'c':
+				memory_cache_trigger = strtoul(optarg, &dummy, 10);
+				break;
 			default:
 				show_usage();
 				exit(EXIT_SUCCESS);
@@ -116,12 +128,21 @@
 		ioctl(fd_watchdog, WDIOC_SETTIMEOUT, &watchdog_time);
 		printf("The watchdog timeout has been set to %d seconds\n", watchdog_time);
 	}
-	
+
 	while(1){
-		if(0 == find_processes(proc_monitor, num_to_monitor))
+		if(0 == find_processes(proc_monitor, num_to_monitor)) {
+//			printf("Hit the dog\n");
 			write(fd_watchdog, "\0", 1);
-		// Sleep between checking for processes
+		}
+		/* Sleep between checking for processes */
 		usleep(1000 * sleep_val);
+		/* check to see if the free memory is below what we want.  if so, clean it out. */
+		if (!sysinfo(&sys_info)) {
+			if (memory_cache_trigger > (sys_info.freeram / (1024 * sys_info.mem_unit))) 
+				try_to_free_cache(3);
+		} else 
+			/* Can't get sys info spec, assume I need to free up memory */
+			try_to_free_cache(3);
 	}
 	
 	return 0;
@@ -130,7 +151,7 @@
 /* Display command line usage */
 static void show_usage(void)
 {
-	printf("procwatch - Watchdog monitor for one or more processes\n");  
+	printf("procwatch - Watchdog monitor for one or more processes (and disk cache monitor)\n");  
 	printf("Usage: \n");  
 	printf("procwatch [-t <time in mS>] [-w <watchdog timer value in seconds>] [-p <process name>] [-d] \n");  
 	printf("\t\t-t - specified time to sleep between checks (in milliseconds)\n");  
@@ -138,6 +159,9 @@
 	printf("\t\t-p - specific process name to monitor.  Program waits for the process to become active.\n");
 	printf("\t\t     After the program is active, it must stay alive for the watchdog to be refreshed.\n"); 
 	printf("\t\t     There can be multiple processes monitored by the program.\n"); 
+	printf("\t\t-c - Number of kilobytes under which free memory must go that triggers a cleanup the system disk cache.\n");
+	printf("\t\t     (The disk cache eats up free memory which causes the free memory sysinfo to be \n");
+	printf("\t\t      non-indicative of the actual memory available) \n");
 	printf("\t\t-d - run the program as a daemon. (Not supported under uClinux.)\n");
 	printf("\t\t-? - See this usage.\n");
 	
@@ -167,11 +191,10 @@
 	char 			status[128];
 	char 			buf[128];
 
-	if(0 == list_len) {
+	if(0 == list_len) 
 		return 0;
-	} else if( 0 > list_len) {
+	else if( 0 > list_len) 
 		return -1;
-	}
 	
 	dir = opendir("/proc");
 	if(!dir)
@@ -180,42 +203,38 @@
 	/* Initialize the list to all invalid processes */
 	for(n = 0, unfound_process = 0, offline_process = 0; n < list_len; n++){
 		list[n].valid = 0; 	
-		if(0 != list[n].online){	/* This process is online, we must find it in proc */
+		if(0 != list[n].online)	/* This process is online, we must find it in proc */
 			unfound_process++;
-		} else {
+		else 
 			offline_process++;
-		}
 		
 	}
 		
 /* while I have not accounted for all the processes I need to check */
 	while(0 < unfound_process || 0 < offline_process) {
 		if((entry = readdir(dir)) == NULL) 
-			/* cannot read more entries, time to get out */
-			break; 
+			break; 			/* cannot read more entries, time to get out */
 		proc_id_name = entry->d_name;
-		if (!(*proc_id_name >= '0' && *proc_id_name <= '9')) {/* look for decimal numeric name */
+		if (!(*proc_id_name >= '0' && *proc_id_name <= '9')) /* look for decimal numeric name */
 			continue;
-		}
+
 		pid = atoi(proc_id_name);
-		if(0 >= pid) {
+		if(0 >= pid) 
 			continue;
-		}			
 		
 		buf[0] = '\0';	/* Insure termination of string */
 		sprintf(status, "/proc/%d/status", pid);
-		if((fp = fopen(status, "r")) == NULL){
+		if((fp = fopen(status, "r")) == NULL)
 			continue;
-		}
 		
 		/* Find the Name line in the status file */
 		n = 0;
 		valid_line = 0;
 		while(0 != valid_line || !feof(fp)) {
 			/* Append data from the file into the raw buffer */
-			if((x=fread(&buf[n], 1, sizeof(buf)-1-n, fp)) > 0) {
+			if((x=fread(&buf[n], 1, sizeof(buf)-1-n, fp)) > 0) 
 				n = x+n;
-			}
+			
 			/* extract a terminated line from the buffer */
 			for(valid_line = 0, x = 0; x < n && x < 128; x++) {
 				if(buf[x] == '\n' || buf[x] == '\r' ) { 
@@ -228,22 +247,20 @@
 					n = y;
 					buf[n] = '\0';
 					break;
-				} else if( ' ' > buf[x]) {
+				} else if( ' ' > buf[x]) 
 					status[x] = ' '; 
-				} else {
+				else 
 					status[x] = buf[x]; 
-				}
 			}
 			/* see if this line starts with the desired line header*/
 			if(valid_line) {
-				/* set cmd_line to point to string after header name */
+				/* set cmd_line to point to string after header name, must be first item on the line */
 				if(NULL != (cmd_line= strstr( status, STATUS_LINE_ARG))) {
 					cmd_line += strlen(STATUS_LINE_ARG);
 					break;
 				} 
-			} else {
+			} else 
 				cmd_line = NULL;
-			}
 		}
 		fclose(fp);
 		
@@ -271,3 +288,88 @@
 	return unfound_process;
 }	
 
+#if 0  /* Using more direct sysinfo 
+/* 
+ *	This function determine the number of KB allocated to page frame cache 
+ * 	The value is extracted from the /proc/meminfo proc file. 
+ */
+int memory_in_cache(void)
+{
+	char 	status[128];
+	char 	buf[256];
+	int 	valid_line;
+	FILE  	* fp;
+	int		x, y, n;
+	char 	*cmd_line;
+	long 	memory_amount = -1;
+	
+	if((fp = fopen("/proc/meminfo", "r")) == NULL){
+		return -1; 
+	}
+	valid_line = 0;
+	n = 0;
+	while(0 != valid_line || !feof(fp)) {
+		/* Append data from the file into the raw buffer */
+		if((x=fread(&buf[n], 1, sizeof(buf)-1-n, fp)) > 0) {
+			n = x+n;
+		}
+		/* extract a terminated line from the buffer */
+		for(valid_line = 0, x = 0; x < n && x < 256; x++) {
+			if(buf[x] == '\n' || buf[x] == '\r' ) { 
+				status[x] = '\0';
+				valid_line = 1;
+				x++;
+				for(y = 0; x < n; y++, x++) {
+					buf[y] = buf[x];
+				} 
+				n = y;
+				buf[n] = '\0';
+				break;
+			} else if( ' ' > buf[x]) {
+				status[x] = ' '; 
+			} else {
+				status[x] = buf[x]; 
+			}
+		}
+		/* see if this line starts with the desired line header*/
+		if(valid_line) {
+			/* set cmd_line to point to string after header name */
+			if(NULL != (cmd_line= strstr( status, CACHED_MEMORY_ARG)) && cmd_line == status) {
+				cmd_line += strlen(CACHED_MEMORY_ARG);
+				while(' ' == *cmd_line)
+					cmd_line++;
+				memory_amount = strtoul(cmd_line, NULL, 10);
+				break;
+			} 
+		} else {
+			cmd_line = NULL;
+		}
+	}
+	fclose(fp);
+	return memory_amount;
+}
+#endif
+
+/* 
+ *	This function tries to force the system to clean out page frame cache.  
+ *	It uses teh /proc/sys/vm/drop_caches tuanble to indicate to the OS to clean up the 
+ * 	page frame cache. 
+ */
+void try_to_free_cache(int val)
+{
+	FILE 	*fp;
+	char	type[4];
+	if((fp = fopen("/proc/sys/vm/drop_caches", "w")) == NULL)
+		return;
+	
+	type[1] = '\n';
+	type[2] = '\0';
+	if(val == 1) 
+		type[0] = '1';	
+	else if(val == 2) 
+		type[0] = '2';
+	else 
+		type[0] = '3';
+	fwrite(type, 1, 3, fp);
+	fclose(fp);
+}




More information about the aadk-commits mailing list