My question: How to get the process status (Running/Stopped) using pid, using C in solaris. Solution: Process's info is stored into psinfo of /proc/<pid>/ and its structure is defined in /usr/include/sys/procfs.h (typedefed psinfo_t) If you want to know process's status (ie. R,S,W etc...) you should examine pr_flag of psinfo_t structure. its type is int and its mean is also defined in same file. Thanks zoo11@mail.hst.co.kr and Karl Vogel for answering my question Thanks Johan Hartzenberg for your discovery Please find below the c code sent by Karl Vogel ----------------------------------------------- --------------------------------------------------------------------------- /* * ftp://ftp.eng.auburn.edu/pub/doug/qps.c * A very fast ps that goes through procfs * @(#)qps.c 1.21 08/02/97 Doug Hughes Auburn University */ #include <stdio.h> #include <sys/types.h> #include <sys/fcntl.h> #include <sys/procfs.h> #include <string.h> #include <stdlib.h> #include <pwd.h> #include <dirent.h> #include <sys/mkdev.h> #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif static int reverse=0; typedef struct qps { int pid; char ppid[40]; char tty[3]; char user[9]; float cpu; float mem; char pname[17]; char *arglist; } *QPS; void usage() { puts("qps [-acdmnptruPU]"); puts(" -a show initial (80 chars of) process args"); puts(" -A show ALL arguments"); puts(" -c sort by CPU usage"); puts(" -d debug (will print process ID before opening process)"); puts(" -e display environment variables"); puts(" -m sort by memory usage"); puts(" -n sort by process name"); puts(" -p sort py pid"); puts(" -P show parent process and PGID"); puts(" -t sort by tty"); puts(" -r reverse order sorting"); puts(" -s memory size info SIZE and RSS in pages and bytes (respectively)"); puts(" -u sort by user"); puts(" -U do not attempt to do uid->username mapping (Save CPU)"); exit(1); } int sort_by_pid(const void *farg1, const void *farg2) { QPS arg1, arg2; arg1 = (QPS) farg1; arg2 = (QPS) farg2; if (reverse) return(arg2->pid > arg1->pid); else return(arg1->pid > arg2->pid); } int sort_by_cpu(const void *farg1, const void *farg2) { QPS arg1, arg2; arg1 = (QPS) farg1; arg2 = (QPS) farg2; if (reverse) return(arg2->cpu < arg1->cpu); else return(arg1->cpu < arg2->cpu); } int sort_by_mem(const void *farg1, const void *farg2) { QPS arg1, arg2; arg1 = (QPS) farg1; arg2 = (QPS) farg2; if (reverse) return(arg2->mem < arg1->mem); else return(arg1->mem < arg2->mem); } int sort_by_tty(const void *farg1, const void *farg2) { QPS arg1, arg2; arg1 = (QPS) farg1; arg2 = (QPS) farg2; if (reverse) return(strcmp(arg2->tty, arg1->tty)); else return(strcmp(arg1->tty, arg2->tty)); } int sort_by_user(const void *farg1, const void *farg2) { QPS arg1, arg2; arg1 = (QPS) farg1; arg2 = (QPS) farg2; if (reverse) return(strcmp(arg2->user, arg1->user)); else return(strcmp(arg1->user, arg2->user)); } int sort_by_pname(const void *farg1, const void *farg2) { QPS arg1, arg2; arg1 = (QPS) farg1; arg2 = (QPS) farg2; if (reverse) return(strcmp(arg2->pname, arg1->pname)); else return(strcmp(arg1->pname, arg2->pname)); } /* * Subproc to display all args (as opposed to what's in arglist */ char *showallargs(int fd, struct prpsinfo *p) { /* routine rewritten by Roger Faulkner - procfs co-designer and guru */ char **argv; /* hold arg pointers */ char *env[400]; /* hold environment */ int argc = p->pr_argc; /* arg count */ char buf[BUFSIZ+1]; /* temporary buffer */ int len; /* strlen(buf) */ char *retbuf= NULL; /* to return arglist */ int argsize=64; /* keep argsize for allocation records */ int retbuflen; /* strlen(retbuf) */ int i = 0; char *sp; /* a space character */ if ((retbuf = malloc(argsize)) == NULL) { fprintf(stderr, "Out of memory in malloc!"); exit(1); } retbuf[0] = (char) NULL; retbuflen = 0; buf[BUFSIZ] = (char) NULL; if (argc * sizeof(*argv) <= sizeof(env)) argv = env; /* use local buffer */ else if ((argv = malloc(argc * sizeof(*argv))) == NULL) { fprintf(stderr, "Out of memory in malloc!"); exit(1); } if ((argc = pread(fd, argv, argc * sizeof(*argv), p->pr_argv)) > 0) argc /= sizeof(*argv); for (i = 0; i < argc; i++) { if (argv[i] == NULL || pread(fd, buf, BUFSIZ, argv[i]) <= 0) continue; len = strlen(buf); /* If it's a bunch of spaces (zero'd out by process), skip/trunc it*/ sp = strchr(buf, ' '); if (sp == buf) continue; else if (sp != (char *) NULL) { sp = buf + len; while (*--sp == ' ') { *sp = (char) NULL; len--; } } while (retbuflen + len + 1 >= argsize) { argsize *= 2; if ((retbuf = realloc(retbuf, argsize)) == NULL) { fprintf(stderr, "Out of memory in realloc!"); exit(1); } } if (retbuflen != 0) retbuf[retbuflen++] = ' '; strcpy(retbuf + retbuflen, buf); retbuflen += len; } if (argv != env) /* if we allocated argv */ free(argv); /* free it */ return(retbuf); } /* * subproc to display environment variables */ showenv(int fd, struct prpsinfo *p) { char *env[400]; /* hold environment */ char buf[BUFSIZ]; /* temporary buffer */ int i = 0; pread(fd, env, 400, p->pr_envp); while (env[i] != NULL && i < 400) { pread(fd, buf, BUFSIZ, env[i++]); printf("%s ", buf); } puts(""); } /* * Main program * * fast - regular qps, and qps -d (to find stuck processes waiting on I/O) * qps -a (showargs), * qps -U (don't do NIS/NIS+ lookups), * qps -s (show RSS, SIZE stuff) * * medium - qps -e (has to munge through and grab out environment stuff. * uses read on open descriptor and has to do pointers to pointers) * * slower - sorting of any kind. May get stuck if a process is hung waiting * for I/O. If so, run qps -d. (It's still pretty darned fast) * */ main(int argc, char *argv[]) { struct prpsinfo p; /* process information structure */ struct passwd *pw; /* hold password lookup information */ char rssinfo[80]; /* character resident set/memory info */ DIR *dirf; /* directory file pointer */ char nothing[2]=" "; /* Just empty printing stuff */ struct dirent *dirp; /* directory pointer */ int fd; /* file descriptor */ char c; /* for getopt */ int cnt, i; /* counting and looping */ int mapuid = TRUE; /* Map userid to username? */ register int min, maj; /* Major and minor device numbers */ int (*func)(const void *, const void *) = NULL; /* sorting function pointer */ struct qps pstruct[1024]; /* Process structure */ char parg[15]; /* process name buffer */ char *ppstr = ""; /* parent and pgid */ char *pphdr = " PPID PGID "; /* PPID and PGID headers */ char *ppdelim = ""; /* delimiters for PPID and PGID */ char *ppdelimd="----- ----- "; char ppbuf[40] = ""; /* hold actual ppid and pgid */ /* flags */ int debug = 0; /* debugging flag */ int showargs = 0; /* Show arguments */ int rss = 0; /* Resident set size */ int environ = 0; /* show environment? */ int showppid = 0; /* show parent and pgid */ int Allargs = 0; /* show ALL arguments */ while ((c = getopt(argc, argv, "AadertuUpPcmns")) != -1) { switch(c) { case 'A': if (rss) { puts("rss and argument showing are mutually exclusive"); exit(1); } Allargs = 1; break; case 'a': if (rss) { puts("rss and argument showing are mutually exclusive"); exit(1); } showargs = 1; break; case 'c': func = &sort_by_cpu; break; case 'd': debug = 1; break; case 'e': environ = 1; break; case 'm': func = &sort_by_mem; break; case 'n': func = &sort_by_pname; break; case 'p': func = &sort_by_pid; break; case 'P': showppid = 1; ppdelim = ppdelimd; ppstr = pphdr; break; case 'r': reverse = 1; break; case 's': if (showargs) { puts("rss and argument showing are mutually exclusive"); exit(1); } rss = 1; break; case 't': func = &sort_by_tty; break; case 'u': func = &sort_by_user; break; case 'U': mapuid = FALSE; break; default: usage(); break; } } /* Set line buffering for output */ setvbuf(stdout, NULL, _IOLBF, 1024); if ((dirf = opendir("/proc")) == NULL) { perror("couldn't open proc"); exit(1); } (void) readdir(dirf); /* skip over . and .. */ (void) readdir(dirf); /* Display headers */ printf("%-7s %s%-3.3s %-8.8s %-4.4s %-4.4s %-17.17s", "PID", ppstr, "TTY", "User", "%CPU", "%Mem", "Process Name"); if (rss) /* print process size headers */ printf(" %5s %5s %6s %6s\n", "SIZEP", "RSSP", "SIZE_B", "RSS_B"); else printf("\n"); printf("%-7s %s%-3.3s %-8.8s %-4.4s %-4.4s %-17.17s", "------", ppdelim, "---", "-------", "----", "----", "-----------------"); if (rss) /* print process size headers */ printf(" %5s %5s %6s %6s\n", "-----", "-----", "------", "------"); else printf("\n"); cnt = 0; /* open /procfs and scan through files one at a time - each a process */ while ((dirp = readdir(dirf)) != NULL) { sprintf(parg, "/proc/%s", dirp->d_name); if (debug) printf("process %s\n", dirp->d_name); if ((fd = open(parg, O_RDONLY)) < 0) { continue; } /* Grab process information/status */ if (ioctl(fd, PIOCPSINFO, (void *) &p) < 0) { close(fd); continue; } /* map major and minor device numbers */ min = minor(p.pr_lttydev); maj = major(p.pr_lttydev); /* Show process arguments with name */ if (Allargs) { pstruct[cnt].arglist = showallargs(fd, &p); } else if (showargs) { pstruct[cnt].arglist = strdup(p.pr_psargs); } else if (rss) { sprintf(rssinfo, " %5d %5d %6u %6u", p.pr_size, p.pr_rssize, p.pr_bysize/1024, p.pr_byrssize/1024); pstruct[cnt].arglist = strdup(rssinfo); } else { pstruct[cnt].arglist = nothing; } /* Do we want to see parent and pgrp? */ if (showppid) sprintf(ppbuf, "%5d %5d ", p.pr_ppid, p.pr_pgrp); /* Convert mem and CPU usage to percentage of machine capacity */ pstruct[cnt].pid = p.pr_pid; strcpy(pstruct[cnt].ppid, ppbuf); pstruct[cnt].mem = p.pr_pctmem * 100.0 / (float) 0x8000; pstruct[cnt].cpu = p.pr_pctcpu * 100.0 / (float) 0x8000; /* Get uid/uname */ if (!mapuid || (pw = getpwuid(p.pr_uid)) == NULL) sprintf(pstruct[cnt].user, "%-8d", p.pr_uid); else sprintf(pstruct[cnt].user, "%-8.8s", pw->pw_name); sprintf(pstruct[cnt].pname, "%-16.16s", p.pr_fname); /* check controlling tty if available */ if (p.pr_ttydev == PRNODEV) sprintf(pstruct[cnt].tty, "--"); else if (maj == 0) sprintf(pstruct[cnt].tty, "co"); else sprintf(pstruct[cnt].tty, "%-.1d", min); if (func == NULL) { /* no sorting - just do it */ printf("%-7d %s%-3.2s %-8.8s %4.1f %4.1f %-16.16s %s\n", pstruct[cnt].pid, pstruct[cnt].ppid, pstruct[cnt].tty, pstruct[cnt].user, pstruct[cnt].cpu, pstruct[cnt].mem, pstruct[cnt].pname, pstruct[cnt].arglist); if (environ) showenv(fd, &p); } cnt++; close(fd); } closedir(dirf); /* sorting applied */ if (func != NULL) { qsort((void*) pstruct, cnt, sizeof(struct qps), func); for (i=0; i < cnt; i++) printf("%-7d %s%-3.2s %-8.8s %4.1f %4.1f %-16.16s %s\n", pstruct[i].pid, pstruct[i].ppid, pstruct[i].tty, pstruct[i].user, pstruct[i].cpu, pstruct[i].mem, pstruct[i].pname, pstruct[i].arglist ); } exit(0); } Please find below the Johan Hartzenberg discovery ------------------------------------------------- This question prompted me to try and find the answer myself, purely for curiosity's sake. I have discovered something very very strange! After scanning through a few man pages trying to look for a system function, I did a truss -aef -o /tmp/ps.truss.out ps -o s -p $$ (using ksh, $$ gives 580 in the example below) The way the execution seems to first check the platform specific stuff and then execute the correct "ps" command. Then the ps started to open the files under /proc/*/psinfo ... Every single one of them! Only immediately after process 580 did it write a single " S\n" to standard out. See the extract from the truss below. My guess is that the odd getdents in between is to cater for processes that got created or terminated during the time ps had been running. My surprise is at the seeming inefficient coding! Surely when specifying a list of process IDs, ps only need to open and actually read from the psinfo file belonging to the relevant process(es)! Granted the /proc structure is in memory, but does that justify going through 1000s of processes and actually making three system calls per process, just to print the info for a single process? Back in programming class I learned that calling a function is CPU expensive, despite it's other advantages (Eg the cost of stack operations vs simplified coding). To be sure I compared the results between Solaris 7 and 8, and both acts the same. Also I compared the results between an E250 and an E10K domain, and both were the same. Any comments/thoughts? > zactomud102 [/tmp] # more ps.truss.out 14693: execve("/usr/bin/ps", 0xFFBEFD44, 0xFFBEFD5C) argc = 5 14693: argv: ps -o s -p 580 [snip] 14693: open("/proc/12657/psinfo", O_RDONLY) = 4 14693: read(4, "\f\0 B\b\0\0\004\0\0 1 q".., 416) = 416 14693: close(4) = 0 14693: open("/proc/608/psinfo", O_RDONLY) = 4 14693: read(4, "\b01 B\b\0\0\001\0\002 `".., 416) = 416 14693: close(4) = 0 14693: open("/proc/12862/psinfo", O_RDONLY) = 4 14693: read(4, "\f\0 B\b\0\0\004\0\0 2 >".., 416) = 416 14693: close(4) = 0 14693: open("/proc/12516/psinfo", O_RDONLY) = 4 14693: read(4, "\f\002\b\0\0\003\0\0 0E4".., 416) = 416 14693: close(4) = 0 14693: getdents(3, 0x10010F378, 1048) = 1024 14693: open("/proc/11552/psinfo", O_RDONLY) = 4 14693: read(4, "\f\002\b\0\0\003\0\0 - ".., 416) = 416 14693: close(4) = 0 14693: open("/proc/13035/psinfo", O_RDONLY) = 4 14693: read(4, "\f\002\b\0\0\003\0\0 2EB".., 416) = 416 14693: close(4) = 0 14693: open("/proc/12581/psinfo", O_RDONLY) = 4 14693: read(4, "\b02 B\b\0\0\001\0\0 1 %".., 416) = 416 14693: close(4) = 0 14693: open("/proc/5937/psinfo", O_RDONLY) = 4 14693: read(4, "\f\0 B\b\0\0\005\0\017 1".., 416) = 416 14693: close(4) = 0 14693: open("/proc/5446/psinfo", O_RDONLY) = 4 14693: read(4, "\b\002\b\0\0\001\0\015 F".., 416) = 416 14693: close(4) = 0 14693: open("/proc/29660/psinfo", O_RDONLY) = 4 14693: read(4, "\b\0 B\b\0\0\001\0\0 sDC".., 416) = 416 14693: close(4) = 0 14693: open("/proc/14691/psinfo", O_RDONLY) = 4 14693: read(4, "\b\0 B\b\0\0\001\0\0 9 c".., 416) = 416 14693: close(4) = 0 14693: open("/proc/580/psinfo", O_RDONLY) = 4 14693: read(4, "\b\0 B\b\0\0\001\0\002 D".., 416) = 416 14693: close(4) = 0 14693: write(1, " S\n", 2) = 2 14693: open("/proc/29964/psinfo", O_RDONLY) = 4 14693: read(4, "\b\0 B\b\0\0\001\0\0 u\f".., 416) = 416 14693: close(4) = 0 14693: open("/proc/14365/psinfo", O_RDONLY) = 4 14693: read(4, "\b\0 B\b\0\0\001\0\0 81D".., 416) = 416 14693: close(4) = 0 14693: open("/proc/7102/psinfo", O_RDONLY) = 4 14693: read(4, "\b\0 B\b\0\0\001\0\01BBE".., 416) = 416 14693: close(4) = 0 14693: open("/proc/12633/psinfo", O_RDONLY) = 4 14693: read(4, "\b02 B\b\0\0\001\0\0 1 Y".., 416) = 416 14693: close(4) = 0 14693: open("/proc/12609/psinfo", O_RDONLY) = 4 14693: read(4, "\f\002\b\0\0\003\0\0 1 A".., 416) = 416 14693: close(4) = 0 14693: open("/proc/12582/psinfo", O_RDONLY) = 4 14693: read(4, "\b0202\b\0\0\001\0\0 1 &".., 416) = 416 14693: close(4) = 0 14693: open("/proc/12610/psinfo", O_RDONLY) = 4 14693: read(4, "\f01 B\b\0\0\0\n\0\0 1 B".., 416) = 416 14693: close(4) = 0 [snip] Yahoo! - Official partner of 2002 FIFA World Cup http://fifaworldcup.yahoo.com _______________________________________________ sunmanagers mailing list sunmanagers@sunmanagers.org http://www.sunmanagers.org/mailman/listinfo/sunmanagersReceived on Sat May 25 01:55:52 2002
This archive was generated by hypermail 2.1.8 : Thu Mar 03 2016 - 06:42:44 EST