home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / att-pages < prev    next >
Encoding:
Internet Message Format  |  1988-05-22  |  19.0 KB

  1. Subject:  v15i004:  Page accounting aide for SysVrel3.1
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: DJ Molny <ihnp4!chinet!djmolny>
  6. Posting-number: Volume 15, Issue 4
  7. Archive-name: pages
  8.  
  9.  
  10. "Pages" notes the size and the number of pages in core for each
  11. paging region in the system.  A typical process has three regions:
  12. text (executable instructions), initialized data variables, and
  13. uninitialized variables (called BSS).  Processes may also use
  14. regions to connect to shared libraries, shared memory segments, etc.
  15.  
  16. Notes on portability:  "Pages" is highly dependent on the System V
  17. Release 3.1 implementation, and it has only been tested on the
  18. AT&T 3B2/400 computer.  "Pages" will probably run on all members of
  19. the 3B2 family, but may run on the 3B15 as well.  As far as release
  20. compatability goes, SVR3.0 is probably OK, SVR2.1 *may* work, and
  21. releases prior to 2.1 didn't have paging.
  22.  
  23. #! /bin/sh
  24. #
  25. # -rw-r--r--   1 djmolny  ccom        4072 Feb 19 12:29 README
  26. # -r--r--r--   1 djmolny  ccom       10688 Feb 19 12:26 pages.c
  27. # -rw-r--r--   1 djmolny  ccom        1286 Feb 19 11:20 pages.1
  28. # -rw-r--r--   1 djmolny  ccom         199 Feb 19 10:32 pages.mk
  29. #
  30. echo 'x - README'
  31. if test -f README; then echo 'shar: not overwriting README'; else
  32. sed 's/^X//' << '________This_Is_The_END________' > README
  33. XAT&T's paging UNIX operating system provides two tools to
  34. Xanalyze memory usage.  The sar(1) package collects statistics
  35. Xabout the amount of free memory in the system, and the number of
  36. Xpages and processes moved in and out from the disk swap area.
  37. XThe ps(1) command's "-l" option shows each process' size in pages.
  38. X(1 page = 2Kb.)
  39. X
  40. XUnfortunately, neither sar nor ps tells how many pages from each
  41. Xprocess are in actually core, and how many have been saved to disk.
  42. XTo fill this need, I wrote "pages".  "Pages" works a lot like ps(1).
  43. XIt reads /unix to find kernel symbol addresses, then opens /dev/kmem
  44. Xand rummages around to find the information it wants.  "Pages" saves
  45. Xkernel symbol data in /etc/pg_data to speed up execution.  This file
  46. Xis updated automatically whenever /unix is newer than /etc/pg_data.
  47. X
  48. X"Pages" notes the size and the number of pages in core for each
  49. Xpaging region in the system.  A typical process has three regions:
  50. Xtext (executable instructions), initialized data variables, and
  51. Xuninitialized variables (called BSS).  Processes may also use
  52. Xregions to connect to shared libraries, shared memory segments, etc.
  53. X
  54. XAfter each region has been analyzed, "pages" prints a table of
  55. Xeach process and independent region it has encountered.  The table
  56. Xshows the process id (if appropriate), the number of pages swapped
  57. Xto disk, and total number of pages, and the process' name (if appropriate.)
  58. X
  59. XA typical run of "pages" (with no arguments) may look like this:
  60. X
  61. X1:      PID  NSWAP/TOTL   COMMAND
  62. X2:    SHARE      1   23   sh
  63. X3:    11308      3    8   sh
  64. X4:    18486     12  104   vi
  65. X5:    18498     15   46   pages
  66. X6:    18496      3    8   sh
  67. X
  68. XLine one is column headings.  The second line shows the shared text region
  69. Xof the Bourne shell (indicated by the word "SHARE" in column 1.)  One of
  70. Xits 23 pages is paged out to disk (or was never loaded in the first place.)
  71. XThe third line is the combined data and BSS regions of a shell, with three
  72. Xof the 8 pages on disk.  Since the data are not shared, the specific process
  73. Xid is shown.  Line 6 gives the same information for another shell process.
  74. X
  75. XLine 4 shows that 12 of 104 pages of vi are on disk.  In this case, the
  76. XTOTL column represents the combined text, data, and BSS sizes.  If another
  77. Xuser was running vi, a "SHARE" line show the shared text region separately.
  78. XLine 5 shows "pages" itself.
  79. X
  80. XBy defaults, "pages" only shows processes attached to your current tty.
  81. XTo alter this behavior, the -e, -a, -t, and -u options may be used.
  82. XThese options work the same as on "pages" as they do on "ps", and
  83. Xare explained on the ps(1) man page.  In addition, the -q option may
  84. Xbe used to get a quick look at the system's overall paging status.
  85. X
  86. X"Pages" must run as setuid bin so that it can write the /etc/pg_data file,
  87. Xand as setgid sys so that it can read /dev/kmem.  The makefile supplied
  88. Xwith this package sets ownership and uid/gid bits when the "install"
  89. Xtarget is specified.
  90. X
  91. XNotes on portability:  "Pages" is highly dependent on the System V
  92. XRelease 3.1 implementation, and it has only been tested on the
  93. XAT&T 3B2/400 computer.  "Pages" will probably run on all members of
  94. Xthe 3B2 family, but may run on the 3B15 as well.  As far as release
  95. Xcompatability goes, SVR3.0 is probably OK, SVR2.1 *may* work, and
  96. Xreleases prior to 2.1 didn't have paging.
  97. X
  98. XI had to read and compare /usr/include/sys files and wade through lots of
  99. Xkernel dumps to find the algorithms for this program.  Anyone who wants
  100. Xto port "pages" to a truly foreign implementation will have to do the same.
  101. XI only have access to the 3B2/400, so you're on your own when it comes
  102. Xto porting.  Sorry.
  103. X
  104. XEnhancements and bug reports (preferably with fixes) are welcome but
  105. XI don't promise to incorporate them immediately.  Since netnews often
  106. Xexpires before I get around to reading it, messages should be sent
  107. Xvia E-mail to ihnp4!chinet!djmolny.
  108. X
  109. XThis program is placed in the public domain.  It may be distributed
  110. Xand modified freely providing this notice is reproduced in its entirety.
  111. XThis program may not be sold.  Author: DJ Molny, ccom consultants, inc.
  112. ________This_Is_The_END________
  113. if test `wc -l < README` -ne 79; then
  114.     echo 'shar: README was damaged during transit (should have been 79 bytes)'
  115. fi
  116. fi        ; : end of overwriting check
  117. echo 'x - pages.c'
  118. if test -f pages.c; then echo 'shar: not overwriting pages.c'; else
  119. sed 's/^X//' << '________This_Is_The_END________' > pages.c
  120. X/*
  121. X * pages - show process paging information
  122. X *
  123. X * Written by:    DJ Molny
  124. X *        ccom consultants, inc.
  125. X *        5963 Oakwood Dr.
  126. X *        Lisle, IL 60532
  127. X *        ihnp4!chinet!djmolny
  128. X *
  129. X * This program is placed in the public domain.  It may be distributed
  130. X * and modified freely providing this notice is reproduced in its entirety.
  131. X * This program may not be sold.
  132. X *
  133. X * The "pages" program is highly dependent on AT&T's implementation
  134. X * of the 3B2 UNIX System V Release 3 operating system.  It might be
  135. X * modified to other members of the AT&T 3B family, but porting to
  136. X * other paging implementations of UNIX is probably impossible.
  137. X *
  138. X * Refer to the accompanying manual page for usage instructions and
  139. X * the inevitable disclaimers.
  140. X *
  141. X */
  142. X
  143. X#include <stdio.h>
  144. X#include <sys/types.h>
  145. X#include <nlist.h>
  146. X#include <fcntl.h>
  147. X#include <pwd.h>
  148. X#include <sys/stat.h>
  149. X#include <sys/immu.h>
  150. X#include <sys/psw.h>
  151. X#include <sys/pcb.h>
  152. X#include <sys/signal.h>
  153. X#include <sys/fs/s5dir.h>
  154. X#include <sys/user.h>
  155. X#include <sys/region.h>
  156. X#include <sys/param.h>
  157. X#include <sys/proc.h>
  158. X#include <sys/var.h>
  159. X#include <sys/sysmacros.h>
  160. X#include <sys/sys3b.h>
  161. X
  162. Xstatic char sccsid[] = "@(#)pages.c    1.11 2/19/88";
  163. X
  164. X#define    PNAME    "pages"
  165. X#define DATAFILE "/etc/pg_data"
  166. X
  167. X#define    MAXREAD    (64 * 1024)        /* max bytes to read in one shot */
  168. X
  169. Xstruct nlist ksymbs[] = {
  170. X    "proc",     (long) 0, (short) 0, (unsigned short) 0, (char) 0, (char) 0,
  171. X    "v",        (long) 0, (short) 0, (unsigned short) 0, (char) 0, (char) 0,
  172. X    "freemem",  (long) 0, (short) 0, (unsigned short) 0, (char) 0, (char) 0,
  173. X    (char *) 0, (long) 0, (short) 0, (unsigned short) 0, (char) 0, (char) 0,
  174. X};
  175. X
  176. Xint quick = 0;        /* quick mode (off by default)        */
  177. Xint ttys;        /* tty # to show (defaults to current tty)    */
  178. Xint tflag = 0;        /* tty # specified (off by default)        */
  179. Xint aflag = 0;        /* show all logged in users (off by default)    */
  180. Xint eflag = 0;        /* show all procs (off by default)        */
  181. Xint uids = -1;        /* user id # (defaults to unused)        */
  182. X
  183. Xint memfd;
  184. Xstruct var v;
  185. X
  186. Xstatic struct regblk {        /* pertinent info. for the regions we select */
  187. X    unsigned long pid;
  188. X    char cmd[DIRSIZ];
  189. X    short size;
  190. X    short incore;
  191. X};
  192. X
  193. Xstruct regblk *reg_tab, *reg_cur;    /* ptrs to region table */
  194. X
  195. X#define Error(s)    { perror(s); }
  196. X
  197. X
  198. Xmain(argc, argv)
  199. Xint argc;
  200. Xchar **argv;
  201. X{
  202. X    extern char *optarg;
  203. X    struct passwd *pwd, *getpwnam();
  204. X    struct stat sbuf, sbuf2;
  205. X    char ttynm[128];
  206. X    char *malloc();
  207. X    int datafd;
  208. X    int i;
  209. X
  210. X    while ((i = getopt(argc, argv, "qaeu:t:")) != -1)
  211. X    {
  212. X        switch(i) {
  213. X            case 'q':
  214. X                quick++;
  215. X                eflag++;
  216. X                break;
  217. X            case 'e':
  218. X                eflag++;
  219. X                break;
  220. X            case 'a':
  221. X                aflag++;
  222. X                break;
  223. X            case 'u':
  224. X                if (!optarg) usage();
  225. X                if (*optarg >= '0' && *optarg <= '9')
  226. X                    uids = atoi(optarg);
  227. X                else {
  228. X                    pwd = getpwnam(optarg);
  229. X                    if (!pwd)
  230. X                    {
  231. X                        fprintf(stderr,
  232. X                        "No such user: %s\n", optarg);
  233. X                        usage();
  234. X                    }
  235. X                    uids = pwd->pw_uid;
  236. X                }
  237. X                break;
  238. X            case 't':
  239. X                if (!optarg) usage();
  240. X                tflag++;
  241. X                strcpy(ttynm, "/dev/");
  242. X                if (*optarg >= '0' && *optarg <= '9')
  243. X                    strcat(ttynm, "tty");
  244. X                strcat(ttynm, optarg);
  245. X                if (stat(ttynm, &sbuf) == -1)
  246. X                {
  247. X                    perror(ttynm);
  248. X                    exit(4);
  249. X                }
  250. X
  251. X                ttys = sbuf.st_rdev;
  252. X                break;
  253. X            default:
  254. X                usage();
  255. X        }
  256. X    }
  257. X
  258. X
  259. X    /* for default case (no arguments), act as if
  260. X       we're invoked with our own tty specified */
  261. X
  262. X    if (!aflag && !eflag && !tflag && uids == -1)
  263. X    {
  264. X        tflag++;
  265. X
  266. X        /* check stdin, stdout, stderr for a file
  267. X           descriptor connected to a tty */
  268. X
  269. X        for (i = 0; i < 3; i++)
  270. X            if (isatty(i))
  271. X                break;
  272. X
  273. X        if (i == 3)
  274. X        {
  275. X            fprintf(stderr, "%s: can't find tty\n", PNAME);
  276. X            exit(5);
  277. X        }
  278. X
  279. X        /* stat the tty file */
  280. X        if (fstat(i, &sbuf) == -1)
  281. X        {
  282. X            perror(PNAME);
  283. X            exit(6);
  284. X        }
  285. X
  286. X        /* and extract the internal device number */
  287. X        ttys = sbuf.st_rdev;
  288. X    }
  289. X
  290. X    /* open kernel memory */
  291. X
  292. X    if ((memfd = open("/dev/kmem", O_RDONLY)) == -1)
  293. X    {
  294. X        Error("/dev/kmem");
  295. X        exit(7);
  296. X    }
  297. X
  298. X    /* stat /unix to see if it's changed since
  299. X       we last wrote the data cache file */
  300. X
  301. X    if (stat("/unix", &sbuf) == -1)
  302. X    {
  303. X        Error("/unix");
  304. X        exit(10);
  305. X    }
  306. X
  307. X    /* if our cache file is gone, or if unix is newer than
  308. X       the cache file, do the lengthy nlist() call and re-write
  309. X       the cache */
  310. X
  311. X    if (stat(DATAFILE, &sbuf2) == -1 || sbuf.st_mtime > sbuf2.st_mtime)
  312. X    {
  313. X        if (nlist("/unix", ksymbs) == -1)    /* LONG library call */
  314. X        {
  315. X            Error("nlist");
  316. X            exit(11);
  317. X        }
  318. X
  319. X        /* create/truncate the cache file */
  320. X
  321. X        datafd = open(DATAFILE, O_CREAT | O_WRONLY | O_TRUNC, 0664);
  322. X
  323. X        if (datafd == -1)
  324. X        {
  325. X            Error(DATAFILE);
  326. X            exit(12);
  327. X        }
  328. X
  329. X        /* save the whole name list structure */
  330. X        if (write(datafd, ksymbs, sizeof(ksymbs)) != sizeof(ksymbs))
  331. X        {
  332. X            Error(DATAFILE);
  333. X            exit(13);
  334. X        }
  335. X
  336. X        close(datafd);
  337. X
  338. X    } else {    /* cache is current, so read ksymbs from there */
  339. X
  340. X        datafd = open(DATAFILE, O_RDONLY);
  341. X
  342. X        if (datafd == -1)
  343. X        {
  344. X            Error(DATAFILE);
  345. X            exit(14);
  346. X        }
  347. X
  348. X        /* snarf in the whole array */
  349. X        if (read(datafd, ksymbs, sizeof(ksymbs)) != sizeof(ksymbs))
  350. X        {
  351. X            Error(DATAFILE);
  352. X            exit(16);
  353. X        }
  354. X
  355. X        close(datafd);
  356. X    }
  357. X
  358. X
  359. X    /* seek to the "var" kernel structure (contains tunables) */
  360. X    if (lseek(memfd, ksymbs[1].n_value, 0) == -1)
  361. X    {
  362. X        Error("memory lseek");
  363. X        exit(17);
  364. X    }
  365. X
  366. X    /* and read it */
  367. X    if (read(memfd, &v, sizeof(v)) != sizeof(v))
  368. X    {
  369. X        Error("memory read");
  370. X        exit(18);
  371. X    }
  372. X
  373. X    /* allocate one regblk per region */
  374. X    reg_tab = (struct regblk *) malloc(sizeof(struct regblk) * v.v_region);
  375. X
  376. X    if (reg_tab == NULL)    /* make sure malloc succeeded */
  377. X    {
  378. X        fprintf(stderr, "can't grab %d bytes\n",
  379. X            sizeof(struct regblk) * v.v_region);
  380. X        exit(19);
  381. X    }
  382. X
  383. X    procloop();            /* loop through proc table */
  384. X    showpage();            /* display the paging info */
  385. X
  386. X    return(0);
  387. X}
  388. X
  389. X
  390. Xprocloop()
  391. X{
  392. X    struct user u;
  393. X    struct region r;
  394. X    struct pregion pr;
  395. X    struct proc p;
  396. X    register struct proc *pp;
  397. X    int incore, npages;
  398. X    int i;
  399. X
  400. X    pp = &p;
  401. X    reg_cur = reg_tab;    /* initialize region table ptr */
  402. X
  403. X    /* for each process... */
  404. X    for (i=0; i < v.v_proc; i++)
  405. X    {
  406. X        /* seek to process table */
  407. X        if (lseek(memfd, ksymbs[0].n_value + i * sizeof(p), 0) == -1)
  408. X        {
  409. X            Error("memory lseek");
  410. X            exit(21);
  411. X        }
  412. X
  413. X        if (read(memfd, &p, sizeof(p)) != sizeof(p))
  414. X        {
  415. X            Error("memory read");
  416. X            exit(22);
  417. X        }
  418. X
  419. X        if (!pp->p_stat)    /* if p_stat == 0, no proc in slot */
  420. X            continue;
  421. X
  422. X        /* use handy sys3b call to read the u block */
  423. X        /* (see what I mean about non-portable!?) */
  424. X        if (sys3b(RDUBLK, pp->p_pid, &u, sizeof(u)) == -1)
  425. X            continue;
  426. X
  427. X        /* if we're not showing just any process... */
  428. X        if (!eflag)
  429. X        {
  430. X            if (aflag)    /* show all procs connected to ttys */
  431. X            {
  432. X                if (u.u_ttyp == 0) /* if no tty, ignore */
  433. X                    continue;
  434. X            } else {    /* all procs, subject to tty # & uid */
  435. X
  436. X                /* skip proc if not the right tty */
  437. X                if (tflag && (!u.u_ttyp || ttys != u.u_ttyd))
  438. X                    continue;
  439. X
  440. X                /* skip proc if not the right user id */
  441. X                if (uids != -1 && uids != pp->p_uid)
  442. X                    continue;
  443. X            }
  444. X        }
  445. X
  446. X        incore = npages = 0;    /* init counters */
  447. X
  448. X        while(1)        /* zoom thru region table */
  449. X        {
  450. X            /* lseek may fail if conditions change during our
  451. X               run; therefore this is a non-fatal error */
  452. X            if (lseek(memfd, pp->p_region, 0) != (int) pp->p_region)
  453. X                break;
  454. X
  455. X            /* reads may also fail non-fatally */
  456. X            if (read(memfd, &pr, sizeof(pr)) != sizeof(pr))
  457. X                break;
  458. X
  459. X            /* if region ptr = 0, it's part of the chain */
  460. X            if (!pr.p_reg)
  461. X            {
  462. X                /* log it */
  463. X                logr((unsigned long) pp->p_pid, npages,
  464. X                            incore, u.u_comm);
  465. X                break;
  466. X            }
  467. X
  468. X            /* point to next spot in the chain */
  469. X            pp->p_region++;
  470. X
  471. X            /* go to the region itself */
  472. X            if (lseek(memfd, pr.p_reg, 0) != (int) pr.p_reg)
  473. X                break;
  474. X
  475. X            /* and read it */
  476. X            if (read(memfd, &r, sizeof(r)) != sizeof(r))
  477. X                break;
  478. X
  479. X            /* if it's PRIVATE or only used in one place,
  480. X               count it against the current process */
  481. X            if (r.r_type == RT_PRIVATE || r.r_refcnt == 1)
  482. X            {
  483. X                npages += r.r_pgsz;
  484. X                incore += r.r_nvalid;
  485. X            } else        /* it's shared, so just log it */
  486. X                logs((unsigned long) pr.p_reg, r.r_pgsz,
  487. X                    r.r_nvalid, u.u_comm, pr.p_type);
  488. X        }
  489. X    }
  490. X}
  491. X
  492. X
  493. X/* log a shared region in the table */
  494. X
  495. Xlogs(addr, size, incore, cmd, ptype)
  496. Xchar *addr;
  497. Xint size, incore;
  498. Xchar *cmd;
  499. Xint ptype;
  500. X{
  501. X    register struct regblk *r;
  502. X    char *cmdtype;
  503. X
  504. X    switch(ptype) {
  505. X        case PT_TEXT:    /* for shared text, save the cmd name */
  506. X            cmdtype = cmd;
  507. X            break;
  508. X        case PT_DATA:
  509. X            cmdtype = "<DATA>";
  510. X            break;
  511. X        case PT_STACK:    
  512. X            cmdtype = "<STACK>";
  513. X            break;
  514. X        case PT_SHMEM:
  515. X            cmdtype = "<SHMEM>";
  516. X            break;
  517. X        case PT_DMM:
  518. X            cmdtype = "<DMM>";
  519. X            break;
  520. X        case PT_LIBTXT:
  521. X            cmdtype = "<LIBTXT>";
  522. X            break;
  523. X        case PT_LIBDAT:
  524. X            cmdtype = "<LIBDAT>";
  525. X            break;
  526. X        default:
  527. X            cmdtype = "<OTHER>";    /* punt */
  528. X            break;
  529. X        }
  530. X
  531. X    /* loop thru the region table, looking to see if this one
  532. X       has been entered before (to avoid dups) */
  533. X
  534. X    for (r = reg_tab; r < reg_cur; r++)
  535. X        if (r->pid == (unsigned long) addr)
  536. X            return;
  537. X
  538. X    /* a new region; enter it now */
  539. X    r->pid = (unsigned long) addr;
  540. X    strncpy(r->cmd, cmdtype, DIRSIZ);
  541. X    r->size = size;
  542. X    r->incore = incore;
  543. X
  544. X    reg_cur++;        /* bump table ptr */
  545. X}
  546. X
  547. X
  548. X
  549. X/* log a region in the table */
  550. X
  551. Xlogr(pid, size, incore, cmd)
  552. Xunsigned long pid;
  553. Xint size, incore;
  554. Xchar *cmd;
  555. X{
  556. X    register struct regblk *r = reg_cur;
  557. X
  558. X    r->pid = (unsigned long) pid;    /* save the process id */
  559. X    strncpy(r->cmd, cmd, DIRSIZ);    /* save the cmd name */
  560. X    r->size = size;            /* save the region size */
  561. X    r->incore = incore;        /* save the # of pages in core */
  562. X
  563. X    reg_cur++;            /* bump table ptr */
  564. X}
  565. X
  566. X
  567. Xshowpage()
  568. X{
  569. X    if (quick)
  570. X        show_q();
  571. X    else
  572. X        show_n();
  573. X}
  574. X
  575. X
  576. X/* quick mode */
  577. Xshow_q()
  578. X{
  579. X    register struct regblk *r;
  580. X    int swapped = 0;
  581. X    int incore = 0;
  582. X    int freemem;
  583. X
  584. X    /* zip thru region table, adding up pages in core & pages swapped */
  585. X    for (r = reg_tab; r < reg_cur; r++)
  586. X    {
  587. X        if (!r->size)
  588. X            continue;
  589. X        incore += r->incore;
  590. X        swapped += r->size - r->incore;
  591. X    }
  592. X
  593. X    /* seek to freemem's address */
  594. X    if (lseek(memfd, ksymbs[2].n_value, 0) == -1)
  595. X    {
  596. X        Error("memory lseek");
  597. X        exit(23);
  598. X    }
  599. X
  600. X    /* read freemem */
  601. X    if (read(memfd, &freemem, sizeof(freemem)) != sizeof(freemem))
  602. X    {
  603. X        Error("memory read");
  604. X        exit(24);
  605. X    }
  606. X
  607. X    /* print statitistics */
  608. X    printf("%4d pages free in core\n", freemem);
  609. X    printf("%4d pages active in core\n", incore);
  610. X    printf("%4d pages swapped on disk\n", swapped);
  611. X}
  612. X
  613. X
  614. X/* per-process display */
  615. Xshow_n()
  616. X{
  617. X    register struct regblk *r;
  618. X
  619. X    printf("  PID  NSWAP/TOTL   COMMAND\n");
  620. X
  621. X    /* zip thru region table, printing processes & shared regions */
  622. X    for (r = reg_tab; r < reg_cur; r++)
  623. X    {
  624. X        if (r->pid < 64*1024)
  625. X            printf("%5d", r->pid);
  626. X        else
  627. X            printf("SHARE");
  628. X
  629. X        printf("   %4d %4d   %-.*s\n", r->size - r->incore,
  630. X                        r->size, DIRSIZ, r->cmd);
  631. X    }
  632. X}
  633. X
  634. X
  635. X/* print canned error message */
  636. Xusage()
  637. X{
  638. X    fprintf(stderr,
  639. X        "usage: %s [-e] [-a] [-u user] [-t tty]\n", PNAME);
  640. X    exit(99);
  641. X}
  642. ________This_Is_The_END________
  643. if test `wc -l < pages.c` -ne 522; then
  644.     echo 'shar: pages.c was damaged during transit (should have been 522 bytes)'
  645. fi
  646. fi        ; : end of overwriting check
  647. echo 'x - pages.1'
  648. if test -f pages.1; then echo 'shar: not overwriting pages.1'; else
  649. sed 's/^X//' << '________This_Is_The_END________' > pages.1
  650. X.TH PAGES 1 "2/19/88"
  651. X.UC 4
  652. X.SH NAME
  653. Xpages \- show 3B2 process paging status
  654. X.SH SYNOPSIS
  655. X.B pages
  656. X[-q]
  657. X[-e]
  658. X[-a]
  659. X[-u user]
  660. X[-t tty]
  661. X.SH DESCRIPTION
  662. X.I Pages
  663. Xscans kernel memory, and displays the size and number of swapped-out
  664. Xpages for each process.
  665. XRegions used by multiple processes, such as shared text, shared libraries,
  666. Xand conventional shared memory are also displayed.
  667. X.LP
  668. XThe -e option selects all processes and regions.
  669. XThe -a option selects all processes with a controlling tty.
  670. XThe -u and -t options may be used to select processes by
  671. Xuser id or controlling tty, respectively.
  672. XInvoking
  673. X.I pages
  674. Xwithout arguments is equivalent to using the
  675. X.B -t
  676. Xoption for your own terminal.
  677. X(All of these options work like their corresponding
  678. X.I ps
  679. Xoptions.)
  680. X.LP
  681. XThe -q option displays a three-line summary of pages free in core,
  682. Xpages in use in core, and pages swapped to disk.  Individual processes
  683. Xare not displayed.
  684. X.LP
  685. XOn the 3B2, one page equals 2K bytes of memory.
  686. X.SH "SEE ALSO"
  687. Xps(1)
  688. X.SH AUTHOR
  689. XDJ Molny, ihnp4!chinet!djmolny
  690. X.SH DISCLAIMERS
  691. X.I Pages
  692. Xis highly dependent on the AT&T 3B2 System V Release 3 UNIX implementation.
  693. XIt has only been tested on the AT&T 3B2/400 running SVR3.1.
  694. X.TP
  695. X"UNIX" and "3B" are trademarks of AT&T.
  696. X.SH BUGS
  697. XBugs?  We don't write no stinking bugs!
  698. ________This_Is_The_END________
  699. if test `wc -l < pages.1` -ne 48; then
  700.     echo 'shar: pages.1 was damaged during transit (should have been 48 bytes)'
  701. fi
  702. fi        ; : end of overwriting check
  703. echo 'x - pages.mk'
  704. if test -f pages.mk; then echo 'shar: not overwriting pages.mk'; else
  705. sed 's/^X//' << '________This_Is_The_END________' > pages.mk
  706. XBIN=/usr/local/bin
  707. XCFLAGS=    -O
  708. XLDFLAGS= -s
  709. X
  710. Xpages:    pages.o
  711. X    $(CC) $(LDFLAGS) -o pages pages.o
  712. X
  713. Xinstall: pages
  714. X    mv pages $(BIN)
  715. X    chown bin $(BIN)/pages
  716. X    chgrp sys $(BIN)/pages
  717. X    chmod 6755 $(BIN)/pages
  718. ________This_Is_The_END________
  719. if test `wc -l < pages.mk` -ne 12; then
  720.     echo 'shar: pages.mk was damaged during transit (should have been 12 bytes)'
  721. fi
  722. fi        ; : end of overwriting check
  723. exit 0
  724.