ccs@lazlo.UUCP (Clifford C. Skolnick) (01/15/89)
While cleaning up the hard disk I ran accross this little ditty awhile ago. It is a daemon that runs in the background, takeing very little cpu time, saveing statistics on system load. When it receives a message from the other program provided, it will calculate the load average from the data it has been collecting and send this back to be printed. The code is not pretty, but easy to understand if you know System V IPC already. I wrote this as a little experiment and ment to clean it up and post it, but I never did get motivated to clean it up. At least I'm posting it! As always, any bug reports or suggestions would be appreciated. Please no flames saying lint does not like this code, I already know :-). Cliff #!/bin/sh # shar: Shell Archiver (v1.22) # # Run the following text with /bin/sh to create: # Makefile # la.c # ladaemon.c # sed 's/^X//' << 'SHAR_EOF' > Makefile && Xall: la ladaemon X @echo "type 'make install' to install" X Xinstall: la ladaemon X cp ladaemon /etc/daemons X cp la /usr/local/bin X Xladaemon: ladaemon.o X ld -s ladaemon.o -o ladaemon /lib/crt0s.o /lib/shlib.ifile X Xla: la.o X ld -s la.o -o la /lib/crt0s.o /lib/shlib.ifile X Xladaemon.o: X cc -O -c ladaemon.c X Xla.o: X cc -O -c la.c X X SHAR_EOF chmod 0644 Makefile || echo "restore of Makefile fails" sed 's/^X//' << 'SHAR_EOF' > la.c && X X/* X** la.c (C) 1988 by Cliff Skolnick (ccs@lazlo.UUCP) X** X** X** X** This program gets the load from the ladaemon program. This is done via X** System V message passing. X*/ X X X#define LOGFILE "/usr/adm/la.log" X X#include <sys/types.h> X#include <stdio.h> X#include <sys/ipc.h> X#include <sys/msg.h> X#include <signal.h> X X Xint kmemfd; Xlong ipckey; Xint ipcin; X Xmain() X{ X int ipcout,time_out(); X long retid,tbuf; X double *dindex; X X struct { X long mtype; X char mtext[81]; X } msgp; X X /* key is on the log file */ X if ((ipckey=ftok(LOGFILE,'l'))==-1) { X fprintf(stderr,"la: can\'t get key for %s.\n",LOGFILE); X perror("la"); X exit(1); X } X X /* get that message queue for ladaemon */ X if ((ipcout=msgget(ipckey,0222))==-1) { X fprintf(stderr,"la: IPC msgget() failed for write.\n"); X perror("la"); X exit(1); X } X X /* use the pid as a message queue number for us*/ X retid=(long) getpid(); X X /* make a mail box with that number */ X if ((ipcin=msgget(retid,0666|IPC_CREAT))==-1) { X fprintf(stderr,"la: IPC msgget() failed for read.\n"); X perror("la"); X exit(1); X } X X /* send a message as to where to what queue to put the data */ X msgp.mtype=1L; X *(long *)msgp.mtext=retid; X msgsnd(ipcout,&msgp,sizeof(retid),0); X X /* we'll give ladaemon 5 seconds to respond */ X signal(SIGALRM,time_out); X alarm(5); X X /* keep on going untill a good message is received */ X while (msgrcv(ipcin,&msgp,sizeof(double)*3,0L,0)<0) X sleep(1); X X dindex=(double *)msgp.mtext; X X time(&tbuf); X printf ("%24.24s, load = %.2f, %.2f, %.2f\n",ctime(&tbuf),dindex[0],dindex[1],dindex[2]); X /* kill our queue */ X msgctl(ipcin,IPC_RMID,0); X} X Xtime_out() X{ X fprintf(stderr,"la: no response from ladaemon.\n"); X msgctl(ipcin,IPC_RMID,0); X exit(1); X} SHAR_EOF chmod 0640 la.c || echo "restore of la.c fails" sed 's/^X//' << 'SHAR_EOF' > ladaemon.c && X/* X** X** ladaemon - Program to sample and keep track of system information X** pertaining to load average every 10 seconds. The information is X** processed and sent to user processes upon request using the System V IPC X** mechanism. X** X** Author: Cliff Skolnick (ccs@lazlo.UUCP) X** (C) 1988 X** X*/ X X X#define LOGFILE "/usr/adm/la.log" X X#include <sys/types.h> X#include <stdio.h> X#include <a.out.h> X#undef n_name X#include <fcntl.h> X#include <sys/sysinfo.h> X#include <sys/ipc.h> X#include <sys/msg.h> X#include <signal.h> X X Xstruct nlist nl[] = { X "sysinfo", 0, 0, 0, 0, 0, X "", 0, 0, 0, 0, 0 X}; X Xint kmemfd; Xlong ipckey; Xint logfd; Xint gotalrm; Xstruct sysinfo mysys; X Xunsigned long listocc[61]; Xunsigned long listque[61]; Xunsigned long cpuidle[61]; X X Xmain() X{ X int i,savecur(); X X /* wake up parent */ X if (fork()!=0) X exit(0); X X /* up priority, speed should be as fast as possible so as to get the X information back to the user process before it times out */ X nice(-40); X X /* flag all entries as un-used */ X for (i=0;i<61;i++) X listocc[i]=-1; X X /* get the address of the sysinfo structure */ X if (nlist("/unix", nl) == -1) { X fprintf(stderr, "ladaemon: unable to perform nlist()\n"); X perror("ladaemon"); X exit(1); X } X if (nl[0].n_value == 0) { X fprintf(stderr, "ladaemon: nlist() returned null\n"); X perror("ladaemon"); X exit(1); X } X X /* make sure /dev/kmem is openable */ X if ((kmemfd = open("/dev/kmem", O_RDONLY)) == -1) { X fprintf(stderr, "ladaemon: unable open /dev/kmem\n"); X perror("ladaemon"); X exit(1); X } X X logfd=open(LOGFILE,O_WRONLY|O_CREAT,0644); X if (logfd==0 || (ipckey=ftok(LOGFILE,'l'))==-1) { X fprintf(stderr,"ladaemon: Problem with key\n"); X perror("ladaemon"); X exit(1); X } X close (0); X close (1); X close (2); X dup(logfd); X dup(logfd); X dup(logfd); X close (logfd); X setpgrp(); X X savecur(); X doserve(); X} X X Xdoserve() X{ X int savecur(); X int ipcin,ipcout,i; X double la1,la5,la10,*dindex,insload; X long retid; X struct { X long mtype; X char mtext[81]; X } msgp; X X if ((ipcin=msgget(ipckey,0622|IPC_CREAT))==-1) { X fprintf(stderr,"ladaemon: IPC msgget() failed for read.\n"); X perror("ladaemon"); X exit(1); X } X X i=0; X while (1) { X while (i!=sizeof(retid)) { X i=msgrcv(ipcin,&msgp,sizeof(retid),0L,0); X } X X retid=*(long *)msgp.mtext; X if ((ipcout=msgget(retid,0644|IPC_CREAT))==-1) { X fprintf(stderr,"ladaemon: IPC msgget() failed for write.\n"); X perror("ladaemon"); X exit(1); X } X X gotalrm=1; X while (gotalrm) { X la1=la5=la10=0.0; X gotalrm=0; X for (i=60;i>0;i--) { X if (listocc[i]==-1) X continue; X insload=(double)(listque[i-1]-listque[i]) X /(double)(listocc[i-1]-listocc[i]) X -((double)cpuidle[i-1]-(double)cpuidle[i])/600.0; X la10+=insload; X if (i<31) { X la5+=insload; X if (i<7) X la1+=insload; X } X } X } X X la1/=6.0; X la5/=30.0; X la10/=60.0; X X dindex=(double *)msgp.mtext; X *(dindex++)=la1; X *(dindex++)=la5; X *(dindex++)=la10; X msgp.mtype=1L; X msgsnd(ipcout,&msgp,sizeof(double)*3,IPC_NOWAIT); X } X} X Xsavecur() X{ X int i; X X gotalrm++; X if (lseek(kmemfd, nl[0].n_value, 0) != -1 && X read(kmemfd, (char *)&mysys, sizeof(mysys)) != -1) { X for (i=60;i>0;i--) { X listque[i]=listque[i-1]; X listocc[i]=listocc[i-1]; X cpuidle[i]=cpuidle[i-1]; X } X *listque=mysys.runque; X *listocc=mysys.runocc; X *cpuidle=mysys.cpu[CPU_IDLE]; X } X signal(SIGALRM,savecur); X alarm(10); X} SHAR_EOF chmod 0640 ladaemon.c || echo "restore of ladaemon.c fails" exit 0 -- Cliff Skolnick (ccs@lazlo)| "You told me time makes it easy, but you never Phone: (716) 427-8046 | told me time stands still" - Gary Numan TCP/IP: 44.68.0.195 | ...!rutgers!rochester!ritcv!ritcsh!sabin! lazlo!ccs ccs@lazlo.n1dph.ampr.org| \!kodak!pcid!gizzmo!/