]> Zhao Yanbai Git Server - minix.git/commitdiff
Top, welcome to minix.
authorBen Gras <ben@minix3.org>
Thu, 16 Mar 2006 01:29:51 +0000 (01:29 +0000)
committerBen Gras <ben@minix3.org>
Thu, 16 Mar 2006 01:29:51 +0000 (01:29 +0000)
Minix, welcome to the world of top.

A from-scratch top implementation for minix!

commands/simple/Makefile
commands/simple/top.c [new file with mode: 0644]

index eac38e2cacc8d328532d5b8756d55620216d2640..143f6991e5a6eefb9a116ba6c169bb6a7eca9014 100755 (executable)
@@ -188,6 +188,7 @@ ALL = \
        tget \
        time \
        touch \
+       top \
        tr \
        truncate \
        treecmp \
@@ -808,6 +809,9 @@ touch:      touch.c
        $(CCLD) -o $@ $?
        @install -S 4kw $@
 
+top:   top.c
+       $(CCLD) -o $@ $?
+
 tr:    tr.c
        $(CCLD) -o $@ $?
        @install -S 4kw $@
@@ -1077,6 +1081,7 @@ install:  \
        /usr/bin/termcap \
        /usr/bin/tget \
        /usr/bin/time \
+       /usr/bin/top \
        /usr/bin/touch \
        /usr/bin/tr \
        /usr/bin/treecmp \
@@ -1610,6 +1615,9 @@ install:  \
 /usr/bin/time: time
        install -cs -o bin $? $@
 
+/usr/bin/top:  top
+       install -cs -o bin $? $@
+
 /usr/bin/touch:        touch
        install -cs -o bin $? $@
 
diff --git a/commands/simple/top.c b/commands/simple/top.c
new file mode 100644 (file)
index 0000000..ca44433
--- /dev/null
@@ -0,0 +1,259 @@
+
+#define _MINIX 1
+#define _POSIX_SOURCE 1
+
+#include <stdio.h>
+#include <pwd.h>
+#include <timers.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <termcap.h>
+#include <termios.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+
+#include <sys/ioc_tty.h>
+#include <sys/times.h>
+#include <sys/types.h>
+
+#include <minix/ipc.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/const.h>
+
+#include "../../servers/pm/mproc.h"
+#include "../../kernel/const.h"
+#include "../../kernel/proc.h"
+
+char  *Tclr_all;
+#define  TC_BUFFER  1024        /* Size of termcap(3) buffer    */
+#define  TC_STRINGS  200        /* Enough room for cm,cl,so,se  */
+
+int print_memory(struct pm_mem_info *pmi)
+{
+        int h;
+        int largest_bytes = 0, total_bytes = 0; 
+        for(h = 0; h < _NR_HOLES; h++) {
+                if(pmi->pmi_holes[h].h_base && pmi->pmi_holes[h].h_len) {
+                        int bytes;
+                        bytes = pmi->pmi_holes[h].h_len << CLICK_SHIFT;
+                        if(bytes > largest_bytes) largest_bytes = bytes;
+                        total_bytes += bytes;
+                }
+        }
+
+       printf("Mem: %dK Free, %dK Contiguous Free\n",
+               total_bytes/1024, largest_bytes/1024);
+
+       return 1;
+}
+
+int print_load(double *loads, int nloads)
+{
+       int i;
+       printf("load averages: ");
+       for(i = 0; i < nloads; i++)
+               printf("%s %.2f", (i > 0) ? "," : "", loads[i]);
+       printf("\n");
+       return 1;
+}
+
+#define PROCS (NR_PROCS+NR_TASKS)
+
+int print_proc_summary(struct proc *proc)
+{
+       int p, alive, running, sleeping;
+
+       alive = running = sleeping = 0;
+
+       for(p = 0; p < PROCS; p++) {
+               if(p - NR_TASKS == IDLE)
+                       continue;
+               if(proc[p].p_rts_flags & SLOT_FREE)
+                       continue;
+               alive++;
+               if(proc[p].p_rts_flags & ~SLOT_FREE)
+                       sleeping++;
+               else
+                       running++;
+       }
+       printf("%d processes: %d running, %d sleeping\n",
+               alive, running, sleeping);
+       return 1;
+}
+
+static struct tp {
+       struct proc *p;
+       int ticks;
+} tick_procs[PROCS];
+
+int cmp_ticks(const void *v1, const void *v2)
+{
+       struct tp *p1 = (struct tp *) v1, *p2 = (struct tp *) v2;
+       if(p1->ticks < p2->ticks)
+               return 1;
+       if(p1->ticks > p2->ticks)
+               return -1;
+       if(p1->p->p_nr < p2->p->p_nr)
+               return -1;
+       if(p1->p->p_nr > p2->p->p_nr)
+               return 1;
+       return 0;
+}
+
+void print_procs(int maxlines,
+       struct proc *proc1, struct proc *proc2, int dt,
+       struct mproc *mproc)
+{
+       int p, nprocs;
+       int idleticks = 0;
+
+       for(p = nprocs = 0; p < PROCS; p++) {
+               if(proc2[p].p_rts_flags & SLOT_FREE)
+                       continue;
+               tick_procs[nprocs].p = proc2 + p;
+               tick_procs[nprocs].ticks =
+                       proc2[p].p_user_time-proc1[p].p_user_time;
+               if(p-NR_TASKS == IDLE) {
+                       idleticks = tick_procs[nprocs].ticks;
+                       continue;
+               }
+               nprocs++;
+       }
+
+       qsort(tick_procs, nprocs, sizeof(tick_procs[0]), cmp_ticks);
+
+       printf("CPU states: %5.2f%% user, %5.2f%% idle\n\n",
+               100.0*(dt-idleticks)/dt, 100.0*idleticks/dt);
+       maxlines -= 2;
+
+       printf("  PID USERNAME PRI NICE   SIZE STATE   TIME    CPU COMMAND\n");
+       maxlines--;
+       for(p = 0; p < nprocs; p++) {
+               int euid = 0;
+               struct passwd *who = NULL;
+               struct proc *pr;
+               int pnr, ticks;
+               char *name = "";
+
+               if(maxlines-- <= 0) break;
+
+               pnr = tick_procs[p].p->p_nr;
+               pr = tick_procs[p].p;
+               ticks = pr->p_user_time;
+               if(pnr >= 0) {
+                       printf("%5d ", mproc[pnr].mp_pid);
+                       euid = mproc[pnr].mp_effuid;
+                       name = mproc[pnr].mp_name;
+               } else  {
+                       printf("[%3d] ", pnr);
+                       name = pr->p_name;
+               }
+               who = getpwuid(euid);
+
+               if(who && who->pw_name) printf("%-8s ", who->pw_name);
+               else if(pnr >= 0) printf("%8d ", mproc[pnr].mp_effuid);
+               else printf("         ");
+
+               printf(" %2d ", pr->p_priority);
+               if(pnr >= 0) {
+                       printf(" %3d ", mproc[pnr].mp_nice);
+               } else printf("     ");
+               printf("%5dK",
+                       ((pr->p_memmap[T].mem_len + 
+                       pr->p_memmap[D].mem_len) << CLICK_SHIFT)/1024);
+               printf("%6s", pr->p_rts_flags ? "" : "RUN");
+               printf(" %3d:%02d ", (ticks/HZ/60), (ticks/HZ)%60);
+
+               printf("%5.2f%% %s\n",
+                       100.0*tick_procs[p].ticks/dt, name);
+       }
+}
+
+void showtop(void)
+{
+#define NLOADS 3
+       double loads[NLOADS];
+       int nloads, i, p, lines = 0;
+       static struct proc prev_proc[PROCS], proc[PROCS];
+       struct winsize winsize;
+        static struct pm_mem_info pmi;
+       static int prev_uptime, uptime;
+       static struct mproc mproc[NR_PROCS];
+       struct tms tms;
+
+       uptime = times(&tms);
+
+       if(ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize) != 0) {
+               perror("TIOCGWINSZ");
+               fprintf(stderr, "TIOCGWINSZ failed\n");
+               exit(1);
+       }
+
+        if(getsysinfo(PM_PROC_NR, SI_MEM_ALLOC, &pmi) < 0) {
+               fprintf(stderr, "getsysinfo() for SI_MEM_ALLOC failed.\n");
+               exit(1);;
+       }
+
+       if(getsysinfo(PM_PROC_NR, SI_KPROC_TAB, proc) < 0) {
+               fprintf(stderr, "getsysinfo() for SI_KPROC_TAB failed.\n");
+               exit(1);
+       }
+
+       if(getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc) < 0) {
+               fprintf(stderr, "getsysinfo() for SI_PROC_TAB failed.\n");
+               exit(1);
+       }
+
+       if((nloads = getloadavg(loads, NLOADS)) != NLOADS) {
+               fprintf(stderr, "getloadavg() failed - %d loads\n", nloads);
+               exit(1);
+       }
+
+
+
+       printf("%s", Tclr_all);
+
+       lines += print_load(loads, NLOADS);
+       lines += print_proc_summary(proc);
+       lines += print_memory(&pmi);
+
+       print_procs(winsize.ws_row - lines - 2, prev_proc,
+               proc, uptime-prev_uptime, mproc);
+
+       memcpy(prev_proc, proc, sizeof(prev_proc));
+       prev_uptime = uptime;
+}
+
+void init(void)
+{
+       char  *term;
+       static char   buffer[TC_BUFFER], strings[TC_STRINGS];
+       char *s = strings;
+
+       if(!(term = getenv("TERM"))) {
+               fprintf(stderr, "No TERM set\n");
+               exit(1);
+       }
+
+       if ( tgetent( buffer, term ) != 1 ) {
+               fprintf(stderr, "tgetent failed for term %s\n", term);
+               exit(1);
+       }
+
+       if ( (Tclr_all = tgetstr( "cl", &s )) == NULL )
+               Tclr_all = "\f";
+}
+
+int main(int argc, char *argv[])
+{
+       init();
+
+       while(1) {
+               showtop();
+               sleep(5);
+       }
+}
+