[comp.unix.questions] Help about shared memory

asjoshi@phoenix.Princeton.EDU (Amit S. Joshi) (02/15/88)

Hi,

I wanted to share some data between two processes. I looked up the
manual and found something called "shared memory". Could somebody tell
me waht that is and how do I use it ?

I naively tried something like this:

typdef struct { int flag; char buf[80];} mydat;

main() {
	mydat *dat;
	int sid,pid;

	if ((sid = shmget(IPC_PRIVATE,sizeof(mydat),IPC_CREAT)) < 0) {
		perror("no shared memory");
		exit(1);
	}
	dat = (mydat *)shmat(sid,0,0);
	sprintf(dat->buf,"this is a test");
	dat->flag = 1;
	
	if ((pid = fork()) < 0) {
		perror("no fork");
		exit(1);
	}
	
	if (pid == 0) {
		printf("%s\n",dat->buf);
	} else {
		wait(0);
		printf("%s\n",dat->buf);
	}
}

I simply got a core dump and with dbx I found that the data->buf "was
a nil pointer" or some such thing, and sprintf caused the crash due to a
invalid memory access.

Could somebody help me ??

Thanks,

-- 
Amit Joshi	BITNET	|	Q3696@PUCC.BITNET
		USENET	| {seismo, rutgers}\!princeton\!phoenix\!asjoshi
"There's a pleasure in being mad... which none but madmen know!" - St.Dryden

stroyan@hpfcdc.HP.COM (Mike Stroyan) (02/17/88)

The problem is in the shmget call.  When a new segment is created, it
has permissions determined by the shmflg parameter.  Your shmget call
produced a shared memory segment with 000 permissions, so the shmat
call failed the permissions check.

Changing -
	if ((sid = shmget(IPC_PRIVATE,sizeof(mydat),IPC_CREAT)) < 0) {

to-
	if ((sid = shmget(IPC_PRIVATE,sizeof(mydat),IPC_CREAT | 0600)) < 0) {

will fix your program.

You should be careful to clean up any shared memory segments or semaphores
that your test programs leave around.  They will remain until you remove
them or the system is rebooted.  Since there aren't very many per system,
it is easy to run out if they aren't cleaned up.  You can see what exists
with the ipcs command and remove them with the ipcrm command.

Mike Stroyan, [hplabs!]hpfcla!stroyan

ajohnson@killer.UUCP (Andy Johnson) (02/19/88)

In article <1739@phoenix.Princeton.EDU>, asjoshi@phoenix.Princeton.EDU (Amit S. Joshi) writes:
> I wanted to share some data between two processes. I looked up the
> manual and found something called "shared memory". Could somebody tell
> me waht that is and how do I use it ?

I wrote a multi-user bbs and wanted to use shared memory to facilitate
communications between users, specifically for "chat".  I wrote this
simple program to test the shared memory facilities of Microport.  It
worked find and I have been using shared memory for over a year without
a problem.  Hope this helps.

Andy Johnson
{inhp4!codas!}!killer!ajohnson
---------------
CUT HERE.......
---------------
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
 
#define MEMORY	0x62627321		/* string = "bbs!"  */
#define MAX_PRG 5
#define ERROR -1
 
typedef struct mpstr
{
    unsigned char	lst_in;
    unsigned char	in_recd;
    unsigned char	lst_ot;
    unsigned char	ot_recd;
    unsigned char	whoami[30];
    unsigned char	who_chat;
    unsigned char	on_line;
} MEMPRG;
 
typedef struct memstr
{
    int		wrtflg;
    MEMPRG	memprg[MAX_PRG];
} MEMSTR;
 
char name[80] ="THIS IS A STRING";
 
main(argc, argv)
int argc;
char **argv[];
{
    MEMSTR *memptr;
    char *memget();
    int pgmno;
 
    pgmno = 0;
    if (argc >1)
	pgmno = 1;
 
    printf("\nProgram = %d\n",pgmno);
    printf("\nName = %s\n",name);
    memptr = (MEMSTR*)memget();
    memptr->memprg[pgmno].on_line = 1;
    /* strcpy(memptr->memprg[pgmno].whoami,"USER XXX");*/
    printf("\nput it into memory!\n");
    printf("\nid=%s\n",memptr->memprg[0].whoami);
    printf("\nid=%s\n",memptr->memprg[1].whoami);
    printf("\nName = %s\n",name);
 
    remmem(memptr);
    printf("\nAll done!\n");
    exit(0);
}
 
 
char *memget()
{
    char *shmat();
    char *memadr;
    int mid;
 
    mid = shmget(MEMORY,sizeof(MEMSTR),(IPC_CREAT | 0666));
    if (mid == ERROR)
    {
	printf("\nError getting memory errno = %d\n",errno);
	exit(1);
    }
    printf("\nmid = %d\n",mid);
 
    memadr = shmat(mid,(char*)0,0);
    if (memadr == -1L)
    {
	printf("\nAttach failed %d\n",errno);
	exit(1);
    }
    printf("\nMemory attached at %lx\n",memadr);
 
    return(memadr);
 
}
 
 
remmem(memadr)
char *memadr;
{
    int result;
 
    result = shmdt(memadr);
    if (result == ERROR)
    {
	printf("\nCan't detach memory error %d\n",errno);
	exit(1);
    }
}