unusual function refrences


 
Thread Tools Search this Thread
Top Forums Programming unusual function refrences
# 8  
Old 02-10-2005
Quote:
Originally Posted by Neo
You can find the functions in any good C programming reference book for the system calls used by the OS you are using (which, BTW, you did not specify).

You could also search the net and get a copy of the source code for top, and look at the code Smilie

Thanks, my OS is SunOS and Linux.

The question is I don't have such a good C programming book. All the books that I have and can find only provide common lib functions and system calls.

Thanks, I would try the top source code and find some useful hints.
# 9  
Old 02-11-2005
The Linux versiom of top has evolved to read the /proc file system.
# 10  
Old 02-11-2005
BTW: you can find the source for top here:

ftp://ftp.groupsys.com/pub/top

Reference (below) linux top.c

Code:
/*
 * top - a top users display for Unix
 *
 * SYNOPSIS:  Linux 1.2.x, 1.3.x, using the /proc filesystem
 *
 * DESCRIPTION:
 * This is the machine-dependent module for Linux 1.2.x or 1.3.x.
 *
 * LIBS:
 *
 * CFLAGS: -DHAVE_GETOPT
 *
 * AUTHOR: Richard Henderson <rth@tamu.edu>
 */

#include "top.h"
#include "machine.h"
#include "utils.h"

#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/vfs.h>

#include <sys/param.h>		/* for HZ */
#include <asm/page.h>		/* for PAGE_SHIFT */
#include <linux/tasks.h>	/* for NR_TASKS */

#if 0
#include <linux/proc_fs.h>	/* for PROC_SUPER_MAGIC */
#else
#define PROC_SUPER_MAGIC 0x9fa0
#endif

#define PROCFS "/proc"
extern char *myname;
extern uid_t proc_owner(pid_t pid);

/*=PROCESS INFORMATION==================================================*/

struct top_proc
{
    pid_t pid;
    uid_t uid;
    char name[64];
    int pri, nice;
    unsigned long size, rss;	/* in k */
    int state;
    unsigned long time;
    double pcpu, wcpu;
};
    

/*=STATE IDENT STRINGS==================================================*/

#define NPROCSTATES 7
static char *state_abbrev[NPROCSTATES+1] =
{
    "", "run", "sleep", "disk", "zomb", "stop", "swap",
    NULL
};

static char *procstatenames[NPROCSTATES+1] =
{
    "", " running, ", " sleeping, ", " uninterruptable, ",
    " zombie, ", " stopped, ", " swapping, ",
    NULL
};

#define NCPUSTATES 4
static char *cpustatenames[NCPUSTATES+1] =
{
    "user", "nice", "system", "idle",
    NULL
};

#define NMEMSTATS 6
static char *memorynames[NMEMSTATS+1] =
{
    "K used, ", "K free, ", "K shd, ", "K buf  Swap: ",
    "K used, ", "K free",
    NULL
};

static char fmt_header[] =
"  PID X        PRI NICE  SIZE   RES STATE   TIME   WCPU    CPU COMMAND";


/*=SYSTEM STATE INFO====================================================*/

/* these are for calculating cpu state percentages */

static long cp_time[NCPUSTATES];
static long cp_old[NCPUSTATES];
static long cp_diff[NCPUSTATES];

/* for calculating the exponential average */

static struct timeval lasttime;

/* these are for keeping track of processes */

#define HASH_SIZE	(NR_TASKS * 3 / 2)
static struct top_proc ptable[HASH_SIZE]; 
static struct top_proc *pactive[NR_TASKS];
static struct top_proc **nextactive;

/* these are for passing data back to the machine independant portion */

static int cpu_states[NCPUSTATES];
static int process_states[NPROCSTATES];
static int memory_stats[NMEMSTATS];

/* usefull macros */
#define bytetok(x)	(((x) + 512) >> 10)
#define pagetok(x)	((x) << (PAGE_SHIFT - 10))
#define HASH(x)		(((x) * 1686629713U) % HASH_SIZE)

/*======================================================================*/

static inline char *
skip_ws(const char *p)
{
    while (isspace(*p)) p++;
    return (char *)p;
}
    
static inline char *
skip_token(const char *p)
{
    while (isspace(*p)) p++;
    while (*p && !isspace(*p)) p++;
    return (char *)p;
}

 
int
machine_init(statics)
    struct statics *statics;
{
    /* make sure the proc filesystem is mounted */
    {
	struct statfs sb;
	if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC)
	{
	    fprintf(stderr, "%s: proc filesystem not mounted on " PROCFS "\n",
		    myname);
	    return -1;
	}
    }

    /* chdir to the proc filesystem to make things easier */
    chdir(PROCFS);

    /* initialize the process hash table */
    {
	int i;
	for (i = 0; i < HASH_SIZE; ++i)
	    ptable[i].pid = -1;
    }

    /* fill in the statics information */
    statics->procstate_names = procstatenames;
    statics->cpustate_names = cpustatenames;
    statics->memory_names = memorynames;

    /* all done! */
    return 0;
}


void
get_system_info(info)
    struct system_info *info;
{
    char buffer[4096+1];
    int fd, len;
    char *p;

    /* get load averages */
    {
	fd = open("loadavg", O_RDONLY);
	len = read(fd, buffer, sizeof(buffer)-1);
	close(fd);
	buffer[len] = '\0';

	info->load_avg[0] = strtod(buffer, &p);
	info->load_avg[1] = strtod(p, &p);
	info->load_avg[2] = strtod(p, &p);
	p = skip_token(p);			/* skip running/tasks */
	p = skip_ws(p);
	if (*p)
	    info->last_pid = atoi(p);
	else
	    info->last_pid = -1;
    }

    /* get the cpu time info */
    {
	fd = open("stat", O_RDONLY);
	len = read(fd, buffer, sizeof(buffer)-1);
	close(fd);
	buffer[len] = '\0';

	p = skip_token(buffer);			/* "cpu" */
	cp_time[0] = strtoul(p, &p, 0);
	cp_time[1] = strtoul(p, &p, 0);
	cp_time[2] = strtoul(p, &p, 0);
	cp_time[3] = strtoul(p, &p, 0);

	/* convert cp_time counts to percentages */
	percentages(4, cpu_states, cp_time, cp_old, cp_diff);
    }

    /* get system wide memory usage */
    {
	char *p;

	fd = open("meminfo", O_RDONLY);
	len = read(fd, buffer, sizeof(buffer)-1);
	close(fd);
	buffer[len] = '\0';

	/* be prepared for extra columns to appear be seeking
	   to ends of lines */

	p = strchr(buffer, '\n');
	p = skip_token(p);			/* "Mem:" */
	p = skip_token(p);			/* total memory */
	memory_stats[0] = strtoul(p, &p, 10);
	memory_stats[1] = strtoul(p, &p, 10);
	memory_stats[2] = strtoul(p, &p, 10);
	memory_stats[3] = strtoul(p, &p, 10);

	p = strchr(p, '\n');
	p = skip_token(p);			/* "Swap:" */
	p = skip_token(p);			/* total swap */
	memory_stats[4] = strtoul(p, &p, 10);
	memory_stats[5] = strtoul(p, &p, 10);

	memory_stats[0] = bytetok(memory_stats[0]);
	memory_stats[1] = bytetok(memory_stats[1]);
	memory_stats[2] = bytetok(memory_stats[2]);
	memory_stats[3] = bytetok(memory_stats[3]);
	memory_stats[4] = bytetok(memory_stats[4]);
	memory_stats[5] = bytetok(memory_stats[5]);
    }

    /* set arrays and strings */
    info->cpustates = cpu_states;
    info->memory = memory_stats;
}


static void
read_one_proc_stat(pid_t pid, struct top_proc *proc)
{
    char buffer[4096], *p;

    /* grab the proc stat info in one go */
    {
	int fd, len;

	sprintf(buffer, "%d/stat", pid);

	fd = open(buffer, O_RDONLY);
	len = read(fd, buffer, sizeof(buffer)-1);
	close(fd);

	buffer[len] = '\0';
    }

    proc->uid = proc_owner(pid);

    /* parse out the status */
    
    p = buffer;
    p = strchr(p, '(')+1;			/* skip pid */
    {
	char *q = strrchr(p, ')');
	int len = q-p;
	if (len >= sizeof(proc->name))
	    len = sizeof(proc->name)-1;
	memcpy(proc->name, p, len);
	proc->name[len] = 0;
	p = q+1;
    }

    p = skip_ws(p);
    switch (*p++)
    {
      case 'R': proc->state = 1; break;
      case 'S': proc->state = 2; break;
      case 'D': proc->state = 3; break;
      case 'Z': proc->state = 4; break;
      case 'T': proc->state = 5; break;
      case 'W': proc->state = 6; break;
    }
    
    p = skip_token(p);				/* skip ppid */
    p = skip_token(p);				/* skip pgrp */
    p = skip_token(p);				/* skip session */
    p = skip_token(p);				/* skip tty */
    p = skip_token(p);				/* skip tty pgrp */
    p = skip_token(p);				/* skip flags */
    p = skip_token(p);				/* skip min flt */
    p = skip_token(p);				/* skip cmin flt */
    p = skip_token(p);				/* skip maj flt */
    p = skip_token(p);				/* skip cmaj flt */
    
    proc->time = strtoul(p, &p, 10);		/* utime */
    proc->time += strtoul(p, &p, 10);		/* stime */

    p = skip_token(p);				/* skip cutime */
    p = skip_token(p);				/* skip cstime */

    proc->pri = strtol(p, &p, 10);		/* priority */
    proc->nice = strtol(p, &p, 10);		/* nice */

    p = skip_token(p);				/* skip timeout */
    p = skip_token(p);				/* skip it_real_val */
    p = skip_token(p);				/* skip start_time */

    proc->size = bytetok(strtoul(p, &p, 10));	/* vsize */
    proc->rss = pagetok(strtoul(p, &p, 10));	/* rss */

#if 0
    /* for the record, here are the rest of the fields */
    p = skip_token(p);				/* skip rlim */
    p = skip_token(p);				/* skip start_code */
    p = skip_token(p);				/* skip end_code */
    p = skip_token(p);				/* skip start_stack */
    p = skip_token(p);				/* skip sp */
    p = skip_token(p);				/* skip pc */
    p = skip_token(p);				/* skip signal */
    p = skip_token(p);				/* skip sigblocked */
    p = skip_token(p);				/* skip sigignore */
    p = skip_token(p);				/* skip sigcatch */
    p = skip_token(p);				/* skip wchan */
#endif
}


caddr_t
get_process_info(struct system_info *si,
		 struct process_select *sel,
		 int (*compare)())
{
    struct timeval thistime;
    double timediff, alpha, beta;

    /* calculate the time difference since our last check */
    gettimeofday(&thistime, 0);
    if (lasttime.tv_sec)
    {
	timediff = ((thistime.tv_sec - lasttime.tv_sec) +
		    (thistime.tv_usec - lasttime.tv_usec) * 1e-6);
    }
    else
	timediff = 1e9;
    lasttime = thistime;

    /* calculate constants for the exponental average */
    if (timediff < 30.0)
    {
	alpha = 0.5 * (timediff / 30.0);
	beta = 1.0 - alpha;
    }
    else
	alpha = beta = 0.5;
    timediff *= HZ;  /* convert to ticks */

    /* mark all hash table entries as not seen */
    {
	int i;
	for (i = 0; i < HASH_SIZE; ++i)
	    ptable[i].state = 0;
    }

    /* read the process information */
    {
	DIR *dir = opendir(".");
	struct dirent *ent;
	int total_procs = 0;
	struct top_proc **active = pactive;

	int show_idle = sel->idle;
	int show_uid = sel->uid != -1;

	memset(process_states, 0, sizeof(process_states));

	while ((ent = readdir(dir)) != NULL)
	{
	    struct top_proc *proc;
	    pid_t pid;
	    unsigned long otime;

	    if (!isdigit(ent->d_name[0]))
		continue;

	    pid = atoi(ent->d_name);

	    /* look up hash table entry */
	    proc = &ptable[HASH(pid)];
	    while (proc->pid != pid && proc->pid != -1)
	    {
		if (++proc == ptable+HASH_SIZE)
		    proc = ptable;
	    }

	    otime = proc->time;

	    read_one_proc_stat(pid, proc);

	    if (proc->state == 0)
		continue;

	    total_procs++;
	    process_states[proc->state]++;

	    if (proc->pid == -1)
	    {
		proc->pid = pid;
		proc->wcpu = proc->pcpu = proc->time / timediff;
	    }
	    else
	    {
		proc->pcpu = (proc->time - otime) / timediff;
		proc->wcpu = proc->pcpu * alpha + proc->wcpu * beta;
	    }

	    if ((show_idle || proc->state == 1 || proc->pcpu) &&
		(!show_uid || proc->uid == sel->uid))
	    {
		*active++ = proc;
	    }
	}
	closedir(dir);

	si->p_active = active - pactive;
	si->p_total = total_procs;
	si->procstates = process_states;
    }

    /* flush old hash table entries */
    {
	int i;
	for (i = 0; i < HASH_SIZE; ++i)
	    if (ptable[i].state == 0)
		ptable[i].pid = -1;
    }

    /* if requested, sort the "active" procs */
    if (compare && si->p_active)
	qsort(pactive, si->p_active, sizeof(struct top_proc *), compare);

    /* don't even pretend that the return value thing here isn't bogus */
    nextactive = pactive;
    return (caddr_t)0;
}


char *
format_header(uname_field)
    char *uname_field;
{
    int uname_len = strlen(uname_field);
    if (uname_len > 8)
	uname_len = 8;

    memcpy(strchr(fmt_header, 'X'), uname_field, uname_len);

    return fmt_header;
}


char *
format_next_process(handle, get_userid)
     caddr_t handle;
     char *(*get_userid)();
{
    static char fmt[128];	/* static area where result is built */
    struct top_proc *p = *nextactive++;

    sprintf(fmt,
	    "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %.14s",
	    p->pid,
	    (*get_userid)(p->uid),
	    p->pri,
	    p->nice,
	    format_k(p->size),
	    format_k(p->rss),
	    state_abbrev[p->state],
	    format_time(p->time / HZ),
	    p->wcpu * 100.0,
	    p->pcpu * 100.0,
	    p->name);

    /* return the result */
    return (fmt);
}


/*
 *  proc_compare - comparison function for "qsort"
 *	Compares the resource consumption of two processes using five
 *  	distinct keys.  The keys (in descending order of importance) are:
 *  	percent cpu, cpu ticks, state, resident set size, total virtual
 *  	memory usage.  The process states are ordered as follows (from least
 *  	to most important):  WAIT, zombie, sleep, stop, start, run.  The
 *  	array declaration below maps a process state index into a number
 *  	that reflects this ordering.
 */


int
proc_compare (pp1, pp2)
    struct top_proc **pp1, **pp2;
{
    static unsigned char sort_state[] =
    {
	0,	/* empty */
	6, 	/* run */
	3,	/* sleep */
	5,	/* disk wait */
	1,	/* zombie */
	2,	/* stop */
	4	/* swap */
    };

    struct top_proc *p1, *p2;
    int result;
    double dresult;

    /* remove one level of indirection */
    p1 = *pp1;
    p2 = *pp2;

    /* compare percent cpu (pctcpu) */
    dresult = p2->pcpu - p1->pcpu;
    if (dresult != 0.0)
	return dresult > 0.0 ? 1 : -1;

    /* use cputicks to break the tie */
    if ((result = p2->time - p1->time) == 0)
    {
	/* use process state to break the tie */
	if ((result = (sort_state[p2->state] - sort_state[p1->state])) == 0)
	{
	    /* use priority to break the tie */
	    if ((result = p2->pri - p1->pri) == 0)
	    {
		/* use resident set size (rssize) to break the tie */
		if ((result = p2->rss - p1->rss) == 0)
		{
		    /* use total memory to break the tie */
		    result = (p2->size - p1->size);
		}
	    }
	}
    }

    return result == 0 ? 0 : result < 0 ? -1 : 1;
}


/*
 * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
 *              the process does not exist.
 *              It is EXTREMLY IMPORTANT that this function work correctly.
 *              If top runs setuid root (as in SVR4), then this function
 *              is the only thing that stands in the way of a serious
 *              security problem.  It validates requests for the "kill"
 *              and "renice" commands.
 */

uid_t
proc_owner(pid)
    pid_t pid;
{
    struct stat sb;
    char buffer[32];
    sprintf(buffer, "%d", pid);

    if (stat(buffer, &sb) < 0)
	return -1;
    else
	return sb.st_uid;
}

# 11  
Old 02-11-2005
thanks

thanks, I'll paste the answer when I got it.
# 12  
Old 02-22-2005
something found

1) Using some command (top, procinfo, ...) output is a good choice. So the
problem is how to control the parallel access of the output data. (more than
one client could connet to the server simultaneously)

2) the system call found is not enough to finish the job, like in linux:
int sysinfo(struct sysinfo *info);
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
char _f[22]; /* Pads structure to 64 bytes */
};

In solaris:

kvm_read(system_info, offset, ptr, size) might be useful.


3) the best way is to use /proc files. It would time to understand the structure of each file first and then choose the appropriat files.
If you want to understand /proc files, just "man proc".

That's what I know so far.
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

Script unusual behavior

Hello, I have noticed some unusual behavior while running the script. when i use below script it gives output 355.23 #!/bin/bash ONEDAY=`date +%Y%m%d --date="1 days ago"` cat /opt/occ/var/performance/counters_`date -d "1 day ago" +%Y%m%d`*|grep "Gy,Gy-Gy-CCR"|awk -F"," '{print... (5 Replies)
Discussion started by: scriptor
5 Replies

2. Solaris

Unusual system bog down

Solaris 10 10/09 s10s_u8wos_08a SPARC 16cpus 128MB, uptime 150+ days, 2 db zones (Oracle 9 & 10), 3 application zones. This is from a system that was literally crawling, 60 seconds to execute a single command. I had to reboot to clear it. Data is from runs of prstat and top, and iostat. ... (3 Replies)
Discussion started by: jim mcnamara
3 Replies

3. UNIX for Dummies Questions & Answers

unusual problem with cp command

I have made a simple script to zip a file then first copy it to a specific directory using cp command then move it to another directory. Files are getting generated at regular intervals in the dir. /one/two/three/four/. I have entry of my script in cron to run after every 2 min. #!/bin/sh... (9 Replies)
Discussion started by: Devesh5683
9 Replies

4. Shell Programming and Scripting

Using Awk specify Unusual Delimiter

# echo "size(JFJF" | awk -F"size(" '{print $1}' awk: fatal: Unmatched ( or \(: /size(/ the delimiter is "size(" but i'm not sure if awk is the best tool to use to specify it. i have tried: # echo "size(JFJF" | awk -F"size\(" '{print $1}' awk: warning: escape sequence `\(' treated as... (1 Reply)
Discussion started by: SkySmart
1 Replies

5. HP-UX

Unusual Behavior?

Our comp-operator has come across a peculiar ‘feature'. We have this directory where we save all the reports that were generated for a particular department for only one calendar year. Currently there are 45,869 files. When the operator tried to backup that drive it started to print a flie-listing... (3 Replies)
Discussion started by: vslewis
3 Replies

6. Shell Programming and Scripting

Unusual Problem

what is wrong with the below script: --------------------------------------------------------------------------------- #!/bin/bash echo "Setting JrePath..." grep -w "export JrePath" /etc/profile Export_Status=$? if echo "JrePath declared" elif echo "JrePath not declared" echo... (4 Replies)
Discussion started by: proactiveaditya
4 Replies

7. Programming

C Calender Help - Unusual error

I'm making a program that you input the month and year, and it creates a calender for that month of that year. This is my largest project yet, and I broke it up into several source files. cal.c #include "cal.h" #include <stdio.h> main() { int month, year; scanf("%d %d", &month,... (3 Replies)
Discussion started by: Octal
3 Replies

8. Shell Programming and Scripting

very unusual question about while

is there anyway to make while run a command faster than per second? timed=60 while do command sleep 1 done i need something that can run a script for me more than one time in one second. can someone help me out here? (3 Replies)
Discussion started by: Terrible
3 Replies

9. UNIX for Advanced & Expert Users

unusual function refrences

I'm wrting a program which needs to get the following information of a sever by calling some lib fuctions or system calls, so can anybody help to tell me those function names or where I can find the description of them ? CPU usage Memory usage Load procs per min Swap usage Page I/O Net I/O... (1 Reply)
Discussion started by: xbjxbj
1 Replies
Login or Register to Ask a Question