Article View: comp.sys.next.programmer
Article #687Shared Memory (SYS5) Sources !
From: Thomas Funke
Date: Tue, 14 Apr 1992 15:53
Date: Tue, 14 Apr 1992 15:53
601 lines
16395 bytes
16395 bytes
This is my first version of Shared-Memory-system-5 Calls for NeXT !!
Read the README-File for details and have fun !!
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# README
# ipc.h
# shm.c
# shm.h
# This archive created: Mon Apr 13 21:38:42 1992
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X
XShared Memory for NeXT !
X------------------------
X
XThis is a quick & dirty hack to realize the standard System-V shared-memory
Xcalls on a NeXT.
X
XIf you don't understand this SW, or don't know how to use it, you should
X
X read Stevens W.R, Unix Network programming, Prentice Hall
X
Xand NOT
X
X ask me !
X
XI don't have time to give individual support for this SW. Of course, you
Xcan still hire me.
X
XHowever, if you know how to use this SW and find bugs or improvements,
Xyou're invited to inform me under the following address:
X
X Thomas Funke
X Gasteinerstr. 29
X 1000 Berlin 31
X Germany
X
X E-mail: thf@zelator.in-berlin.de
X
XI'd like to hear from you also if you could get some system-v-pd-sw to
Xrun successfully with these calls. How about POSTGRES-Database ?!
X
X
XHow it works
X------------
X
XThe nice folks at NeXT gave me a hint: there is an undocumented system
Xcall mmap(), which maps some memory to a file. mmap() can be found on
Xother systems, such as sun. So get a man-page for mmap() from you local
Xsun-guru.
X
XThe file can be a zero-length file, thus it just identifies the
Xshared-memory block.
X
XSo for every shared-mem-block I create a file under the directory
X/tmp/.sharedmem. That file has the name
X
X key.shmid.size
X
Xto identify the key, the shmid and the size. The shmid is always dependant
Xon the pid of the process which does the shmget() call.
X
XThe actual attachement will be done with the shmat() call. Usually
Xwe allocate the memory with vm_allocate() and then do a mmap() on
Xthis block and the corresponding file.
X
XThe shmdt() call will free the allocated block and close the file
Xfor which we did the mmap().
X
XFinally, the shmctl() with a command IPC_RMID will remove the
Xfile. You should always use this call to cleanup the .sharedmem-directory.
XTill now, we don't allow any other command for this call, someone is
Xgoing to fix that ?
X
XLook at the sources, I hope they are understandable.
X
X
XHow to install
X--------------
X
XCopy shm.h and ipc.h to /usr/include/sys.
XTranslate shm.c and link it together with you application.
X
XIf you want a demo, run 'cc -DDEBUG shm.c' and run two copies of a.out.
X
XWarning
X-------
X
XThe mmap() system call might be abolished in later versions of NeXT-OS.
XSo programs will not run. I'm not sure about OS3.0, probably it'll still
Xbe ok.
X
XWhat to do next ?
X-----------------
X
XShared memory is very useful only with semaphores. So perhabs someone
Xcan realize the System-V semaphore-calls ? My idea is: Allocate a
Xshared-memory block and then use mach-mutex calls on this. I'm not sure
Xif this would work.
X
XI'll not do this in the near future, so you have to do it yourself!
X
XHave fun.
X
X
X
X
SHAR_EOF
fi # end of overwriting check
if test -f 'ipc.h'
then
echo shar: will not over-write existing file "'ipc.h'"
else
sed 's/^X//' << \SHAR_EOF > 'ipc.h'
X
X/* ipc.h for NeXT
X *
X * Copyright (c) 1992 Thomas Funke
X * thf@zelator.in-berlin.de
X */
X
X/*
XThis program is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation (any version).
X
XThis program is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with this program; see the file COPYING. If not, write to
Xthe Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X#ifndef _IPC_H
X#define _IPC_H
X
X
Xtypedef long key_t; /* We don't have it on NeXT */
X
Xstruct ipc_perm {
X uid_t uid; /* owner's user id */
X gid_t gid; /* owner's group id */
X uid_t cuid; /* creator's user id */
X gid_t cgid; /* creator's group id */
X unsigned short mode; /* access modes */
X unsigned short seq; /* slot usage sequence number */
X key_t key; /* key */
X}; /* Not used yet */
X
X/* IPC operation flag definitions */
X#define IPC_CREAT 0001000 /* create entry if key doesn't exist */
X#define IPC_EXCL 0002000 /* fail if key exists */
X#define IPC_NOWAIT 0004000 /* error if request must wait */
X
X/* Keys. */
X#define IPC_PRIVATE (key_t)0 /* private key */
X
X/* Control Commands. */
X#define IPC_RMID 0 /* remove identifier */
X#define IPC_SET 1 /* set options */
X#define IPC_STAT 2 /* get options */
X
X/* Common ipc_perm mode Definitions. */
X#define IPC_R 0000400 /* read or receive permission */
X#define IPC_W 0000200 /* write or send permission */
X
X#endif
X
X
X
X
X
SHAR_EOF
fi # end of overwriting check
if test -f 'shm.c'
then
echo shar: will not over-write existing file "'shm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'shm.c'
X
X/* shm.c
X * Realizes Shared-Memory for NeXT
X * Copyright (c) 1992 Thomas Funke
X * thf@zelator.in-berlin.de
X */
X
X/*
XThis program is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation (any version).
X
XThis program is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with this program; see the file COPYING. If not, write to
Xthe Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X#include <string.h>
X#include <stdio.h>
X#include <sys/param.h>
X#include <libc.h>
X#include <sys/errno.h>
X#include <sys/mman.h>
X#include <mach.h>
X
X#include "ipc.h"
X#include "shm.h"
X
Xtypedef char String [80];
X
X/* Undocumented mmap function gives us true shared memory */
Xextern char *mmap(caddr_t addr, size_t len, int prot, int flags,
X int fd, off_t off);
X
X/* Max count of shared memory areas for each prozess */
X#define MAX_SHMEM 20
X
X/* Create all Files for mmap in the SHMDIR */
X#define SHMDIR "/tmp/.sharedmem"
X
X/* On error release memory for directory
X * and set errno
X */
X#define RETURN_ERROR(err) { errno = err; freeDir(nlsize); return -1; }
X#define RETURN(val) { freeDir(nlsize); return val; }
X
X/* Store the shared-mem directory */
Xstatic struct direct **namelist;
Xstatic int nlsize;
X
X/* Remember what we have attached */
X
Xstatic struct {
X int shmid; /* Shared memory ID */
X int fd; /* Filedescr. */
X char *mem; /* start of shared memory area */
X int size; /* Size of Block */
X} attached [ MAX_SHMEM] = {0};
X
X/* Remember how many shmget's we did */
Xstatic int getcount = 0;
X
Xstatic int getAttachedEntry (void)
X/* Find a free entry in the attached-Table */
X{
X int i;
X
X for (i=0; i < MAX_SHMEM; i++) {
X if (attached [i].shmid == 0)
X return i;
X }
X
X return -1; /* Not found */
X}
X
Xstatic int openDir(void)
X/* read the SHMDIR and create it if notexistant
X * returns number of entries or -1 if error
X */
X{
X umask (0);
X mkdir (SHMDIR, 0777);
X
X nlsize = scandir (SHMDIR, &namelist, NULL, NULL);
X
X return nlsize;
X}
X
Xstatic freeDir (int nlsize)
X/* Release the Memory for openDir -- don't forget to call ! */
X{
X int i;
X
X for (i=0; i < nlsize; i++) {
X free (namelist[i]);
X }
X
X free (namelist);
X
X}
X
Xstatic int getShmID (int key, int size)
X/* Search in SHMDIR for key
X * if size > actual size return -1 !
X */
X{
X int i;
X struct direct *dp;
X int k = -1, shmid = -1, s = -1;
X
X for (i = 0; i < nlsize; i++) {
X dp = namelist[i];
X
X if (dp->d_name[0] == '.') continue; /* ignore ., .. */
X
X k = -1;
X sscanf (dp->d_name, "%d.%d.%d", &k, &shmid, &s);
X if (k == key) return shmid;
X }
X return -1;
X}
X
Xstatic int newEntry (int key, int size, int shmflag)
X/* create new entry in filesystem, return shmid */
X{
X
X int pid = getpid (), fd;
X String s;
X int shmid = pid * MAX_SHMEM + getcount;
X
X if (getcount > MAX_SHMEM) { /* Too many shmget's */
X errno = ENOMEM;
X return -1;
X }
X
X /* Create new entry */
X sprintf (s, "%s/%d.%d.%d", SHMDIR, key, shmid, size); /* Filename */
X fd = creat (s, shmflag & 0666);
X if (fd < 0) return -1;
X
X close (fd);
X getcount++;
X return shmid; /* shmid is pid * 100 + getcount */
X}
X
Xint shmget (key_t key, int size, int shmflag)
X{
X int fd, shmid;
X String s;
X
X nlsize = openDir ();
X if (nlsize < 0) return -1; /* No success */
X
X if (key == IPC_PRIVATE) {
X RETURN (newEntry (key, size, shmflag));
X }
X
X /* Not a private key */
X
X /* Does key exist ? */
X
X if ((shmid= getShmID (key, size)) < 0) { /* Key does NOT exist */
X if ((shmflag & IPC_CREAT) == 0)
X RETURN_ERROR (ENOENT);
X
X RETURN (newEntry (key, size, shmflag))
X }
X
X if ( (shmflag & IPC_CREAT) && (shmflag & IPC_EXCL))
X RETURN_ERROR (EEXIST);
X
X RETURN(shmid);
X}
X
Xchar *shmat (int shmid, char *addr, int shmflag)
X/* Attach to the shared memory given by shmid */
X{
X int i, fd, mapflag, entry;
X struct direct *dp;
X int k = -1, sid = -1, size = -1;
X char *mapaddr;
X String s;
X
X entry = getAttachedEntry();
X if (entry < 0) { /* Too many shared memory areas */
X errno = ENOMEM;
X return -1;
X };
X
X nlsize = openDir ();
X if (nlsize < 0) return -1; /* No success */
X
X for (i = 0; i < nlsize; i++) {
X dp = namelist[i];
X
X if (dp->d_name[0] == '.') continue; /* ignore ., .. */
X
X sscanf (dp->d_name, "%d.%d.%d", &k, &sid, &size);
X if (shmid == sid) break;
X }
X
X if (shmid != sid)
X RETURN_ERROR (EINVAL);
X
X sprintf (s, "%s/%s", SHMDIR, dp->d_name);
X fd = open(s, O_RDWR, 0);
X if (fd < 0)
X RETURN_ERROR (errno);
X
X if (addr == NULL) { /* Allocate virtual memory */
X if (vm_allocate(current_task(), (vm_address_t *)&mapaddr, size, TRUE)
X != KERN_SUCCESS)
X RETURN_ERROR (ENOMEM);
X }
X else
X mapaddr = addr; /* Not sure if this works .... */
X
X /* Now do the map */
X
X if (shmflag & SHM_RDONLY)
X mapflag = PROT_READ;
X else
X mapflag = PROT_READ | PROT_WRITE;
X
X if ((int) mmap(mapaddr, size, mapflag, MAP_SHARED, fd, 0) < 0)
X RETURN_ERROR (errno);
X
X /* Now enter the values into the 'attached'-Table */
X
X attached[entry].shmid = shmid;
X attached[entry].fd = fd;
X attached[entry].mem = mapaddr;
X attached[entry].size = size;
X
X RETURN (mapaddr);
X}
X
Xint shmdt (char *shmaddr)
X{
X int i;
X
X if (shmaddr == NULL) {
X errno = EINVAL;
X return -1;
X }
X
X for (i = 0; i < MAX_SHMEM; i++) {
X if ((attached[i].shmid != 0) && (attached[i].mem == shmaddr)) {
X vm_deallocate
X (current_task(), (vm_address_t) shmaddr, attached[i].size);
X attached[i].shmid = 0;
X attached[i].mem = NULL;
X close (attached[i].fd);
X return 0;
X }
X }
X
X errno = EINVAL;
X return -1; /* Not found */
X}
X
Xint shmctl (int shmid, int cmd, struct shmid_ds *buf)
X{
X int i, fd, mapflag;
X struct direct *dp;
X int k = -1, sid = -1, size = -1;
X char *mapaddr;
X String s;
X
X if (cmd != IPC_RMID) { /* We have only this ! */
X errno = EINVAL;
X return -1;
X }
X
X nlsize = openDir ();
X if (nlsize < 0) return -1; /* No success */
X
X for (i = 0; i < nlsize; i++) {
X dp = namelist[i];
X
X if (dp->d_name[0] == '.') continue; /* ignore ., .. */
X
X sscanf (dp->d_name, "%d.%d.%d", &k, &sid, &size);
X if (shmid == sid) break;
X }
X
X if (shmid != sid)
X RETURN_ERROR (EINVAL);
X
X sprintf (s, "%s/%s", SHMDIR, dp->d_name);
X if (unlink (s) < 0)
X RETURN_ERROR (errno);
X
X RETURN (0);
X}
X
X#ifdef DEBUG
Xmain()
X/* Run two copies of this program and look at the output */
X{
X int shmid, i;
X
X char * mem;
X
X shmid = shmget (2, 2000, 0666 | IPC_CREAT);
X if (shmid < 0) {
X perror ("shmget");
X exit (1);
X }
X
X mem = shmat (shmid, NULL, 0);
X
X if ((int) mem == -1) {
X perror ("shmat");
X exit (1);
X }
X
X i= 0;
X while (1) {
X *mem = i;
X printf("%d: set to %d\n", getpid(), i);
X sleep(1);
X printf("%d: read %d\n", getpid(), *mem);
X i++;
X }
X
X exit (0);
X}
X#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'shm.h'
then
echo shar: will not over-write existing file "'shm.h'"
else
sed 's/^X//' << \SHAR_EOF > 'shm.h'
X/*
X * Copyright (c) 1992 Thomas Funke
X * thf@zelator.in-berlin.de
X */
X
X/*
XThis program is free software; you can redistribute it and/or modify
Xit under the terms of the GNU General Public License as published by
Xthe Free Software Foundation (any version).
X
XThis program is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY; without even the implied warranty of
XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
XGNU General Public License for more details.
X
XYou should have received a copy of the GNU General Public License
Xalong with this program; see the file COPYING. If not, write to
Xthe Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X
X#ifndef _SHM_H_
X#define _SHM_H_
X
X/*
X * Operation Flags.
X */
X
X#define SHM_RDONLY 010000 /* attach read-only (else read-write) */
X#define SHM_RND 020000 /* round attach address to SHMLBA */
X
Xstruct shmid_ds {
X struct ipc_perm shm_perm; /* operation permission struct */
X int shm_segsz; /* segment size */
X int shm_lpid; /* pid of last shmop */
X int shm_cpid; /* pid of creator */
X unsigned short shm_nattch; /* current # attached */
X unsigned short shm_cnattch; /* in memory # attached */
X time_t shm_atime; /* last shmat time */
X time_t shm_dtime; /* last shmdt time */
X time_t shm_ctime; /* last change time */
X};
X
Xextern int shmget(key_t key, int size, int shmflg);
Xextern char *shmat(int shmid, char *shmaddr, int shmflg);
Xextern int shmdt(char *shmaddr);
Xextern int shmctl(int shmid, int cmd, struct shmid_ds *buf);
X
X/*
X * ipc_perm Mode Definitions.
X */
X#define SHM_R IPC_R /* read permission */
X#define SHM_W IPC_W /* write permission */
X#define SHM_DEST 02000 /* destroy segment when # attached = 0 */
X
X#endif /* _SHM_H_ */
X
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
--
-----------------------------------------------------------------------
Thomas Funke, Gasteinerstr. 29, 1000 Berlin 31, Germany, +49-30-8618224
** Registered NeXT Developer **
E-mail: thf@zelator.in-berlin.de
-----------------------------------------------------------------------
Technical Details
Message-ID:
<IFA22WS@zelator.in-berlin.de>Path:
arc1-ca.pugleaf.net!sparky!uunet!math.fu-berlin.de!zrz.tu-berlin.de!news.netmbx.de!zelator!thfShow Full Headers
Complete Article Headers
Newsgroups: comp.sys.next.programmer Path: arc1-ca.pugleaf.net!sparky!uunet!math.fu-berlin.de!zrz.tu-berlin.de!news.netmbx.de!zelator!thf From: thf@zelator.in-berlin.de (Thomas Funke) Subject: Shared Memory (SYS5) Sources ! Organization: Puplic-Access-Xenix-System Date: Tue, 14 Apr 92 15:53:00 GMT Message-ID: <IFA22WS@zelator.in-berlin.de> Lines: 601