Re: oninit PIDs and Shared memory segments
Posted in 2006
hariog@yahoo.com wrote:
> Hi All,
>
> Many years ago, Madison Pruet you wrote a very useful utility that
> shows all processes on the system and then determines which shared
> memory segments are owned by which process. This utility certainly
> would be very handy, specially when many instances are running on one
> host. Also to identify any detached segment on the box.
>
> Is this utility available on IIUG for download ? If yes, what name ? If
> not, can it be posted on CDI or email to me please.
>
> Thanks a million.
>
The utility works by formating the unix ps and ipcs commands. The
following is a version of the utility which I have working on Linux.
For other platforms, you would need to use 'ps -ef' and change the
parsing a bit.
You can get similar information from onstat -g glo.
The main reason that I wrote this was that I got tired of having to
trace the PPID and PID fields from ps -ef. I wanted an easy way to
determine who spawned what. I added the SHM stuff later on.
The output from the tool looks like:
LEVEL PPID PID COMMAND SHM KEY SERVERNUM/SEG
. . . . . . . . 0 0 1 init
| . . . . . . . 1 1 4 [keventd]
| . . . . . . . 1 1 5 [ksoftirqd/0]
| . . . . . . . 1 1 6 [ksoftirqd/1]
| . . . . . . . 1 1 7 [kswapd]
| . . . . . . . 1 1 8 [kscand]
...
| . . . . . . . 1 1 2580 /usr/sbin/sshd
| . . . . . . . 1 1 2594 xinetd -stayalive -pidfile /v
| | . . . . . . 2 2594 2974 in.telnetd: 192.168.1.102
| | | . . . . . 3 2974 2975 login -- mpruet
| | | | . . . . 4 2975 2976 -bash
| | | | | . . . 5 2976 3457 gdb ./format_ps
| | | | | | . . 6 3457 3459 /home/mpruet/Src/format_ps
| | | | | | | . 7 3459 3463 [ipcs <defunct>]
| | . . . . . . 2 2594 3208 in.telnetd: 192.168.1.102
| | | . . . . . 3 3208 3209 login -- mpruet
| | | | . . . . 4 3209 3210 -bash
| | | | | . . . 5 3210 3458 vim format_ps.c
...
| . . . . . . . 1 1 3280 oninit -iyv 0x52574801 1/1
| . . . . . . . 0x52574802 1/2
| . . . . . . . 0x52574803 1/3
| | . . . . . . 2 3280 3281 oninit -iyv
| | | . . . . . 3 3281 3282 oninit -iyv
| | | . . . . . 3 3281 3283 oninit -iyv
| | | . . . . . 3 3281 3284 oninit -iyv
| | | . . . . . 3 3281 3285 oninit -iyv
| | | . . . . . 3 3281 3286 oninit -iyv
| | | . . . . . 3 3281 3289 oninit -iyv
| | | . . . . . 3 3281 3290 oninit -iyv
| | | . . . . . 3 3281 3291 oninit -iyv
| | | . . . . . 3 3281 3292 oninit -iyv
| . . . . . . . 1 1 3415 oninit -v 0x52584801 2/1
| . . . . . . . 0x52584802 2/2
| . . . . . . . 0x52584803 2/3
| . . . . . . . 0x52584804 2/4
| . . . . . . . 0x52584805 2/5
| | . . . . . . 2 3415 3416 oninit -v
| | | . . . . . 3 3416 3417 oninit -v
| | | . . . . . 3 3416 3418 oninit -v
| | | . . . . . 3 3416 3419 oninit -v
| | | . . . . . 3 3416 3420 oninit -v
| | | . . . . . 3 3416 3421 oninit -v
The code (Redhat 3 Linux) to do this is below.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define PERROR(x) {perror((x)); exit(1);}
typedef struct ps_node {
struct ps_node *next;
struct ps_node *next_sib;
struct ps_node *head_child;
struct ps_node *end_child;
int pid;
int ppid;
char *command;
} ps_t;
typedef struct shm_node {
struct shm_node *next;
pid_t cpid;
char key[40];
long shmid;
} shm_t;
shm_t *shmhead = NULL;
shm_t *shmtail = NULL;
ps_t *pshead = NULL;
ps_t *pstail = NULL;
ps_t *first_ps = NULL;
ps_t *orphan_head = NULL;
int spaceing = 0;
ps_t *orphan_tail = NULL;
ps_t*
allocate_ps_node()
{ ps_t *tps = (ps_t *)calloc(sizeof(char),sizeof(ps_t));
if (!tps)
{ PERROR("allocate_ps_node() malloc");
}
return tps;
}
shm_t*
init_shm_node(char *key, long shmid)
{ shm_t *tps = (shm_t *) calloc(sizeof(char), sizeof(shm_t));
if (!tps)
{ PERROR("allocate_shm_node() calloc");
}
tps->shmid = shmid;
strcpy(tps->key, key);
if (!shmhead)
shmhead = tps;
else shmtail->next = tps;
shmtail = tps;
}
shm_t*
find_shm_node(pid_t cpid)
{ shm_t *tps;
for (tps = shmhead; tps; tps = tps->next)
{ if (tps->cpid == cpid) return tps;
}
return NULL;
}
shm_t*
find_shm_node_by_shmid(long shmid)
{
shm_t *tps;
for (tps = shmhead; tps; tps = tps->next)
if (tps->shmid == shmid) return tps;
return NULL;
}
void
insert_ps_node(ps_t *tps)
{ ps_t *tmpps=pshead;
if (!pshead)
{ pshead = tps;
pstail = tps;
}
else
{ while ((tmpps->next) && (tmpps->next->pid < tps->pid))
{ tmpps = tmpps->next;
}
if (tmpps->next)
{ tps->next = tmpps->next;
tmpps->next = tps;
}
else
{ tmpps->next = tps;
}
}
}
ps_t*
find_ps_node (int pid)
{ ps_t *tps;
for (tps = pshead; tps; tps=tps->next)
{ if (tps->pid == pid) break;
}
return tps;
}
void
link_to_parent(ps_t *tps)
{ ps_t *tpps = find_ps_node(tps->ppid);
if (tpps)
{ if (tpps->head_child)
{ tpps->end_child->next_sib = tps;
}
else tpps->head_child = tps;
tpps->end_child = tps;
}
else
{ if (orphan_head) orphan_tail->next_sib = tps;
else orphan_head = tps;
orphan_tail = tps;
}
}
int
max_depth(ps_t *tps)
{ int max_below_me = 0;
int tnum;
while (tps)
{ if (tps->head_child)
{ tnum = max_depth(tps->head_child);
if (tnum > max_below_me) max_below_me = tnum;
}
tps=tps->next_sib;
}
return (max_below_me + 1);
}
void
print_heading()
{ int tspace = spaceing;
while(tspace-- > 0) printf(" ");
printf("LEVEL PPID PID COMMAND SHM KEY SERVERNUM/SEG\\n");
}
void
print_this_node(int level, ps_t *tps)
{ int tspace = spaceing - level;
int tlev = level;
shm_t *tpnt;
int first_line = 1;
unsigned long tkey=0;
while (tlev--) printf("| ");
while (tspace-- > 0) printf(". ");
printf("%2d %6d %6d %-12s",level, tps->ppid, tps->pid, tps->command);
for (tpnt = shmhead; tpnt; tpnt=tpnt->next)
{ if (tpnt->cpid == tps->pid)
{ if (!first_line)
{ tspace = spa