[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