Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!munnari.OZ.AU!metro!metro!asstdc.scgt.oz.au!nsw.news.telstra.net!act.news.telstra.net!psgrain!usenet.eel.ufl.edu!spool.mu.edu!howland.reston.ans.net!newsfeed.internetmci.com!hunter.premier.net!netnews.worldnet.att.net!ix.netcom.com!netcom.net.uk!dispatch.news.demon.net!demon!awfulhak.demon.co.uk!awfulhak.demon.co.uk!awfulhak.demon.co.uk!not-for-mail From: brian@awfulhak.demon.co.uk (Brian Somers) Newsgroups: comp.unix.bsd.misc,comp.unix.programmer Subject: Re: Using Shared memory... Date: 29 Jun 1996 22:50:11 -0500 Organization: Coverform Ltd. Lines: 177 Message-ID: <4r4thj$102@anorak.coverform.lan> References: <4qt6l2$4o6@taurus.adnc.com> NNTP-Posting-Host: localhost.coverform.lan X-NNTP-Posting-Host: awfulhak.demon.co.uk X-Newsreader: TIN [version 1.2 PL2] Xref: euryale.cc.adfa.oz.au comp.unix.bsd.misc:1195 comp.unix.programmer:39034 Joe Avila (avila@adnc.com) wrote: : Can someone post an example of how shared memory works between two processes? : I need to implement this into some programs I'm writing but I just can get the : jist of it through reading the man pages. All help is greatly appreciated. This isn't really the correct news group - this is not a bsd specific thing. I've cross-posted to comp.unix.programmer. Think of it like creating a file for ipc. Usually, your server creates a "file" of a given size and writes something to it - your client can then read the file. You need some sort of co-ordination too. A good mechanism for this would be a semaphore (although it depends on your application). The server sets it to one after creating the shared memory. When someone wants to muck around with it, they down it to zero, do their mucking around, then up it to one again. A second semaphore is used to make sure that only one server can be started. The example client writes some data (passed on the command line) to the shared memory after outputing what was there. There are three modules in my example, server.h, server.c and client.c: server.h: #define IPCKEY 1234 /* my (well known) shared memory & semaphore key */ #define SHMSIZE 4096 server.c: #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <signal.h> #include <errno.h> #include <stdio.h> #include "server.h" void Finish( int sig ) { signal( sig, SIG_IGN ); } int main() { /* Note: SEM_R & SEM_W aren't defined - despite docs */ int sAccess = ((IPC_R|IPC_W)>>6) + ((IPC_R|IPC_W)>>3) + (IPC_R|IPC_W); int semid = semget( (key_t)IPCKEY, 2, sAccess|IPC_CREAT ); signal( SIGTERM, Finish ); if( semid == -1 ) perror( "semget" ); else { int mAccess, shmid; struct sembuf op; op.sem_num = 1; op.sem_flg = IPC_NOWAIT|SEM_UNDO; op.sem_op = 1; if( semop( semid, &op, 1 ) == -1 ) { perror( "semup(1)" ); return 1; } op.sem_op = -2; if( !(semop( semid, &op, 1 ) == -1 && errno == EAGAIN) ) { fputs( "A server is already running\n", stderr ); return 1; } mAccess = ((SHM_R|SHM_W)>>6) + ((SHM_R|SHM_W)>>3) + (SHM_R|SHM_W); shmid = shmget( (key_t)IPCKEY, SHMSIZE, mAccess|IPC_CREAT ); if( shmid == -1 ) perror( "shmget" ); else { char *Ptr = (char *)shmat( shmid, 0, 0 ); if( !Ptr ) perror( "shmat" ); else { *Ptr = '\0'; /* We've set things up */ op.sem_num = 0; op.sem_flg = SEM_UNDO; op.sem_op = 1; if( semop( semid, &op, 1 ) == -1 ) perror( "semup(0)" ); /* Hang around for a signal */ pause(); /* If someone's in, let them out */ op.sem_op = -1; if( semop( semid, &op, 1 ) == -1 ) perror( "semdown" ); if( shmdt( Ptr ) == -1 ) perror( "shmdt" ); } if( shmctl( shmid, IPC_RMID, 0 ) ) perror( "shmctl(IPC_RMID)" ); } if( semctl( semid, 0, IPC_RMID, 0 ) == -1 ) perror( "semctl(IPC_RMID)" ); } return 0; } client.c: #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <errno.h> #include <stdio.h> #include "server.h" int main( int argc, char *argv[] ) { int Result = -1; int semid; if( argc != 2 ) { fputs( "Usage: client Message\n", stderr ); return 1; } if( semid = semget( (key_t)IPCKEY, 0, 0 ), semid == -1 ) perror( "semget" ); else { int shmid; struct sembuf op; op.sem_num = 0; op.sem_flg = IPC_NOWAIT|SEM_UNDO; op.sem_op = -1; if( semop( semid, &op, 1 ) == -1 ) { perror( "semdown" ); return 1; } shmid = shmget( (key_t)IPCKEY, 0, 0 ); if( shmid == -1 ) perror( "shmget" ); else { /* My go */ char *Ptr = (char *)shmat( shmid, 0, 0 ); if( Ptr ) { printf( "Message was \"%s\"\n", Ptr ); strncpy( Ptr, argv[1], SHMSIZE ); Ptr[ SHMSIZE - 1 ] = '\0'; if( shmdt( Ptr ) == -1 ) perror( "shmdt" ); } } op.sem_op = 1; if( semop( semid, &op, 1 ) == -1 ) { perror( "semup" ); return 1; } } return Result; } -- Brian <brian@awfulhak.demon.co.uk> Don't _EVER_ lose your sense of humour....