[comp.lang.c] Interprocess Communication on UNIX SVR3

bareta@ihuxv.ATT.COM (Benyukhis) (04/19/88)

Good morning usenetters,

Can anyone outthere help me code the producer/consumer problem
in "C".  The prolog is as follows:  the producer has to produce
a char and deposit it in the shareable buffer for consumer to pick it up
from.  Both processes must use binary semaphores as a means of
synchronization.  It looks trivial, but for someone that has never
written anything for more than one process .... In other words,
if anyone has any helpfull hints for me, I would really appreciate it.

Thanks in advance,

Ed.

les@chinet.UUCP (Leslie Mikesell) (04/20/88)

In article <2592@ihuxv.ATT.COM> bareta@ihuxv.ATT.COM (Benyukhis) writes:
>
>Can anyone outthere help me code the producer/consumer problem
>in "C".  The prolog is as follows:  the producer has to produce
>a char and deposit it in the shareable buffer for consumer to pick it up
>from.  Both processes must use binary semaphores as a means of
>synchronization. 

This sounds like you could use a pipe and avoid the need for any
semaphores.  If this is a simple 1 to 1 arrangement, you can just
write producer to output to stdout, and consumer to read from stdin.
Then let the shell set up the pipe with "producer | consumer".  Or,
one program can fork off a child process with a pipe connected (popen()
will do it all for you).
If you have multiple producers/one consumer or they cannot have the
same parent process, you can use a FIFO or named pipe (see mknod(1)
and mknod(2)).
  
  Les Mikesell 

mechjgh@tness7.UUCP (Greg Hackney ) (04/21/88)

In article <2592@ihuxv.ATT.COM> bareta@ihuxv.ATT.COM (Benyukhis) writes:
>the producer has to produce
>a char and deposit it in the shareable buffer for consumer to pick it up
>from.  Both processes must use binary semaphores as a means of
>synchronization.  It looks trivial, but for someone that has never
>written anything for more than one process

I'm not sure if this is what you want, but here are 4 simple
demo programs for writing lines of IPC "messages", open.c, send.c,
receive.c, and close.c.

open 777       # opens a message queue
ipcs           # show the queue status
send 777 text  # send some text
ipcs           # show the queue status
send 777 text1 # send some more text
ipcs           # show the queue status
rec 777        # read some text
rec 777        # read some text
close 777      # close the queue
ipcs           # show the queue status

--
Greg
{ihnp4 | bellcore}!tness1!mechjgh

#!/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:
#	close.c
#	open.c
#	rec.c
#	send.c
# This archive created: Wed Apr 20 18:19:26 1988
export PATH; PATH=/bin:$PATH
if test -f 'close.c'
then
	echo shar: over-writing existing file "'close.c'"
fi
cat << \SHAR_EOF > 'close.c'
/*  close.c */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

main(argc,argv)
int argc;
char *argv[];
{

	int qid;
	int syserr();

	/*see if the queue is open, and get queue ID number */
	if((qid=msgget(atoi(argv[1]),0666 & ~IPC_CREAT))== -1)
		syserr("Queue was not open!\n");

	/*close the queue*/
	if((msgctl(qid,IPC_RMID,NULL)) == -1)
		syserr("Can't close the queue\n");

	printf("Queue closed successfully\n");
	exit(0);
}

syserr(msg)
char *msg;
{
	extern int errno, sys_nerr;
	extern char *sys_errlist[];

	fprintf(stderr,"ERROR: %s (%d", msg, errno);
	if(errno > 0 && errno < sys_nerr)
		fprintf(stderr, ";%s)\n", sys_errlist[errno]);
	else
		fprintf(stderr,")\n");
	exit(1);
}

SHAR_EOF
if test -f 'open.c'
then
	echo shar: over-writing existing file "'open.c'"
fi
cat << \SHAR_EOF > 'open.c'
/*open.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MAXOPEN 20

main(argc,argv)
int argc;
char *argv[];
{
	int id;
	int syserr();

	if((id=openqueue(atoi(argv[1]))) == -1)
		syserr("Can't open a queue\n");
	printf("Queue ID is %ld\n",id);
	exit(0);
}


static int openqueue(key) /* return queue ID; create if necessary */
long key;
{
	static struct{ 
		long key;
		int qid;
	}queues[MAXOPEN];
	int i, avail, qid;
	extern int errno;
	
	avail = -1;
	for(i=0; i < MAXOPEN; i++){
		if(queues[i].key == key)
			return(queues[i].qid);
		if(queues[i].key == 0 && avail == -1)
			avail=i;
	}
	if(avail == -1){
		errno=0;
		return(-1);
	}
	if((qid=msgget(key,0666 | IPC_CREAT))== -1)
		return(-1);
	queues[avail].key = key;
	queues[avail].qid = qid;
	return(qid);
}

syserr(msg)
char *msg;
{
	extern int errno, sys_nerr;
	extern char *sys_errlist[];

	fprintf(stderr,"ERROR: %s (%d", msg, errno);
	if(errno > 0 && errno < sys_nerr)
		fprintf(stderr, ";%s)\n", sys_errlist[errno]);
	else
		fprintf(stderr,")\n");
	exit(1);
}

SHAR_EOF
if test -f 'rec.c'
then
	echo shar: over-writing existing file "'rec.c'"
fi
cat << \SHAR_EOF > 'rec.c'
/*receive.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MSGSIZE 100

struct foo {
	long	mtype;		/* message type */
	char	mtext[100];	/* message text */
};

struct foo buf;

main(argc,argv)
int argc;
char *argv[];
{

	int qid;
	int ret;
	int syserr();

	/* check to see if the message queue has been opened,
           and get the queue ID number */
	if((qid=msgget(atoi(argv[1]),0666 & ~IPC_CREAT))== -1)
		syserr("Queue was not open!\n");
	printf("Got a qid of %d\n",qid);

	/*set the message type*/
	buf.mtype=1;

	/*get the message from queue */
	if((msgrcv(qid,&buf,sizeof(buf) - sizeof(buf.mtype),0L,0)) == -1){
		printf("Return was %d\n",ret);
		syserr("Can't read the queue\n");
		}
	printf("Return was %d\n",ret);
	printf("%s\n",buf.mtext);
	exit(0);
}

syserr(msg)
char *msg;
{
	extern int errno, sys_nerr;
	extern char *sys_errlist[];

	fprintf(stderr,"ERROR: %s (%d", msg, errno);
	if(errno > 0 && errno < sys_nerr)
		fprintf(stderr, ";%s)\n", sys_errlist[errno]);
	else
		fprintf(stderr,")\n");
	exit(1);
}

SHAR_EOF
if test -f 'send.c'
then
	echo shar: over-writing existing file "'send.c'"
fi
cat << \SHAR_EOF > 'send.c'
/*send.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MSGSIZE 100

struct foo {
	long	mtype;		/* message type */
	char	mtext[100];	/* message text */
};

struct foo BUF;

main(argc,argv)
int argc;
char *argv[];
{

	int qid;
	int ret;
	int syserr();

	/*see if the queue is open, and get the queue ID */
	if((qid=msgget(atoi(argv[1]),0666 & ~IPC_CREAT))== -1)
		syserr("Queue was not open!\n");

	/*set the message type*/
	BUF.mtype = 1;
	sprintf(BUF.mtext,"%s\0",argv[2]);

	/*put the message in queue*/
	if((ret=msgsnd(qid,&BUF,sizeof(BUF) - sizeof(BUF.mtype),0)) == -1)
		syserr("Can't send the queue\n");
	printf("Return was %d\n",ret);
	printf("Message queued successfully\n");
	exit(0);
}

syserr(msg)
char *msg;
{
	extern int errno, sys_nerr;
	extern char *sys_errlist[];

	fprintf(stderr,"ERROR: %s (%d", msg, errno);
	if(errno > 0 && errno < sys_nerr)
		fprintf(stderr, ";%s)\n", sys_errlist[errno]);
	else
		fprintf(stderr,")\n");
	exit(1);
}

SHAR_EOF
#	End of shell archive
exit 0