[comp.unix.questions] SUMMARY: How can I use shared memory for Inter Process Communication?

kelley@qucis.queensu.CA (Todd Kelley) (08/23/90)

kelley@qucis.queensu.CA (Todd Kelley):
>My question concerns IPC using sockets and shared memory on a Sun4
>running SunOS 4.01.
>
>I am working on a program consisting of several processes (all with
>a common ancestor) which pass arrays of data to each other through
>sockets.  One process accepts queries from the other processes, gets
>data out of a database and puts it into memory obtained from malloc(),
>then copies it into a socket to the inquiring process.  Once the data
>is sent over the socket, the memory can be freed.
>
>Since all the processes are on the same machine, I would like to pass
>just a pointer to the data through the socket.  I've assumed that such
>a pointer would be required to point into a shared memory segment
>that the receiving process can attach and access.
>
>I would like to use shmget(2) the same way I use malloc(), but from
>RingTFM I get the impression that shared memory is not designed to
>be used this way.  I performed an experiment, and discovered that a
>single process cannot create more than 100 shm segments, implying
>that the system wide limit on shm segments is about 100.  I can't
>guarantee that there will always be less than 100 pending messages.
>
>How is shared memory normally used for IPC of this nature?

-------------------------
From: Anders Christensen <anders@solan.unit.no>

That's right, you can not use getshm() as you use malloc() (that is calling it
several hundreds times, requesting just a few bytes each time. It would be
better to allocate a large shared memory segment, and write your own 
routine to allocate portions of that. 

However, if you *really* want to, you could always build a new kernel on the
machine, that has a higher limit on shared memory segments than 100. That 
would require root priviliges, and would make your program very useless on
(almost) every other machine. 

---------------------------------------
From: jb107@prism.gatech.edu (BURNS,JIM account in header is temporary)

It would be unnecessary to pass a pointer in a socket since related proc's
such as yours can get the base address of the shmseg from shmat(). Your
pointer may not even mean the same thing in another proc's address space.
The return value of shmat would.

Normally you allocate one, or a (small) few segs, requesting the total
amount of memory needed in shmget(2). The following are two excerpts from
a recent similar thread in comp.unix.wizards:

(1):
Probably the easiest way to do this is do typedef a structure, then assign
the return value of shmat() to a pointer to this structure. Then you can
use ptr->fieldname for everything of relevance, and #include these
definitions in each program. (Naturally, use the same compiler for each
program to avoid alignment problems with the structure. When the compiler
&/or the OS change, the alignment may change, but the relative offset
BETWEEN programs does not, so a program that writes to that field will
write to the same location as a program that reads that field. If this
didn't work, FORTRAN programmers wouldn't be able to put COMMON blocks in
shared memory, which I do.)

(2):
Adapted from the HP 9000/800 HP-UX Real Time Programmers Manual:

On shmget(2):

"If your communication application consists of related processes, you
should call shmget(2) with the key parameter set to IPC_PRIVATE in the
following way:

   myshmid = shmget (IPC_PRIVATE, 4096, 0600);

[...explaination of this call to shmget(2)...(deleted by tgk --
see man page)]   This call to
shmget(2) should appear in your program sometime before the fork()
statement so that the child processes in your communication application
will inherit myshmid.

"If your communication application consists of unrelated processes, you
should call shmget(2) with the key parameter set to the return value of
the ftok() subroutine [or just use an ascii representation of a 4
character string that you know will be unique. - JB ] [...] As an example,
all unrelated processes in a communication application can call shmget(2)
in the following [altered - JB ] way:"

   myshmid = shmget (0x50485331, 4096, IPC_CREAT|600);

to use a key of "PHS1".

On shmat(2):

"Once a process has a valid shmid, it usually wants to attach, perhaps to
lock, to read and/or to write to, and then to detach the shared memory
segment. [...]

[...description of shmat() and its parameters...(deleted by tgk)]

BURNS,JIM    (account in header is temporary)
Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a
Internet: gt0178a@prism.gatech.edu
-------------------------------------
From: guy@auspex.com (Guy Harris)

[...mentions building new kernel ...(deleted by tgk)]  As I remember, you stick

	options	SHMMNI=<N>

into your kernel config file, where <N> is the system-wide limit you
want on shm segments, re-rerun "config", rebuild the kernel, and reboot.

Well, I don't know that there's any one way it's used, but another
alternative is to share one big chunk of memory and have your code
parcel it out, rather than sharing individual chunks.

Alternatively, since you are running under a system that supports
"mmap()", you can use "mmap()" to create the shared segments; as long as
you don't keep all the file descriptors for the files from which the
shared segments are mapped open, you're not limited to 100 of them.
-- 

Todd Kelley  (kelley@qucis.queensu.ca)