home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!seismo!dimacs.rutgers.edu!aramis.rutgers.edu!athos.rutgers.edu!mcgrew
- From: mcgrew@athos.rutgers.edu (Charles Mcgrew)
- Newsgroups: comp.sources.sun
- Subject: v03i010: Shared memory source example
- Message-ID: <Oct.25.12.18.51.1991.28461@athos.rutgers.edu>
- Date: 25 Oct 91 16:18:52 GMT
- Organization: Rutgers Univ., New Brunswick, N.J.
- Lines: 923
- Approved: mcgrew@aramis.rutgers.edu
-
- Submitted-by: rwolf@dretor.dciem.dnd.ca (Robert J Wolf)
- Posting-number: Volume 3, Issue 10
- Archive-name: shared-mem
-
- [I did not test these, but as programming examples they look
- very good. -CWM]
-
-
- Enclosed is free-ware sample shared memory programs. It demonstrates how
- to use shared memory to allow one program to sent messages to another
- program.
-
- This example implements a circular buffer inside shared memory. All timing
- and race conditions have been eliminated and no semaphores, no signals and
- no other external access controls are needed. The shared memory does it
- all! In fact the method used is so simple and lightning fast I would be
- surprised if anyone can improve it. Plus it is portable and will probably
- run on all unix versions. I have verified its operation on IBM AIX, DG UX,
- SCO Unix, SunOS. In fact this approach is so simple & effective it could
- be ported to OS/2 or VMS by changing a few system calls to setup the shared
- memory.
-
- If people want their programs to communicate bi-directionally then great,
- use two pieces of shared memory and reverse the consumer and producer roles
- for the second one! The key is not to have more than one process writing
- to the same piece of shared memory.
-
- If people think the programs should use C pointers inside the shared memory
- instead of offsets then you are wrong because two programs may not use the
- same virtual addres to the same shared memory segment. It may work on some
- machines but not all! I know because I found out the hard way.
-
- I highly recommend people use it.
-
- I can currently me reached via e-mail at
- rwolf@dciem.dnd.ca
- uunet!csri.toronto.edu!dciem!rwolf
- Internet: 192.16.207.3
-
- Thank you & good luck
- Robert Wolf
- 56 Shadberry Drive
- North York (Toronto), Ontario
- M2H 3C8 Canada
- (416) 490-8493
-
- Legal Note.
- This software is freely given to the world with the following
- conditions:
- 1) No change to the code and/or the comments must be done. It must be
- distributed exactly as is. Any desired changes should be
- sent to me and I will consider it for update.
- 2) This software may not be published in any form with out my
- express written consent.
-
- 1991 July 17
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: READ.ME makefile run.sh producer.c consumer.c
- # Wrapped by rwolf@accord on Wed Jul 17 10:13:46 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f READ.ME -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"READ.ME\"
- else
- echo shar: Extracting \"READ.ME\" \(2144 characters\)
- sed "s/^X//" >READ.ME <<'END_OF_READ.ME'
- X Enclosed is free-ware sample shared memory programs. It demonstrates how
- X to use shared memory to allow one program to sent messages to another
- X program.
- X
- X This example implements a circular buffer inside shared memory. All timing
- X and race conditions have been eliminated and no semaphores, no signals and
- X no other external access controls are needed. The shared memory does it
- X all! In fact the method used is so simple and lightning fast I would be
- X surprised if anyone can improve it. Plus it is portable and will probably
- X run on all unix versions. I have verified its operation on IBM AIX, DG UX,
- X SCO Unix, SunOS. In fact this approach is so simple & effective it could
- X be ported to OS/2 or VMS by changing a few system calls to setup the shared
- X memory.
- X
- X If people want their programs to communicate bi-directionally then great,
- X use two pieces of shared memory and reverse the consumer and producer roles
- X for the second one! The key is not to have more than one process writing
- X to the same piece of shared memory.
- X
- X If people think the programs should use C pointers inside the shared memory
- X instead of offsets then you are wrong because two programs may not use the
- X same virtual addres to the same shared memory segment. It may work on some
- X machines but not all! I know because I found out the hard way.
- X
- X I highly recommend people use it.
- X
- X I can currently me reached via e-mail at
- X rwolf@dciem.dnd.ca
- X uunet!csri.toronto.edu!dciem!rwolf
- X Internet: 192.16.207.3
- X
- X Thank you & good luck
- X Robert Wolf
- X 56 Shadberry Drive
- X North York (Toronto), Ontario
- X M2H 3C8 Canada
- X (416) 490-8493
- X
- X Legal Note.
- X This software is freely given to the world with the following
- X conditions:
- X 1) No change to the code and/or the comments must be done. It must be
- X distributed exactly as is. Any desired changes should be
- X sent to me and I will consider it for update.
- X 2) This software may not be published in any form with out my
- X express written consent.
- X
- X 1991 July 17
- END_OF_READ.ME
- if test 2144 -ne `wc -c <READ.ME`; then
- echo shar: \"READ.ME\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f makefile -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"makefile\"
- else
- echo shar: Extracting \"makefile\" \(522 characters\)
- sed "s/^X//" >makefile <<'END_OF_makefile'
- X# Makefile for the sample shared memory programs.
- X
- XCFLAGS = -g -a
- X
- XLIBS =
- X
- XPROGRAMS = producer consumer
- X
- X# Generate all the programs
- Xall : $(PROGRAMS)
- X
- Xproducer : producer.c
- X cc $(CFLAGS) -o producer producer.c $(LIBS)
- X
- Xconsumer : consumer.c
- X cc $(CFLAGS) -o consumer consumer.c $(LIBS)
- X
- X# Lint commands for the two programs
- Xlint_producer :
- X lint producer.c > producer.lnt
- X
- Xlint_consumer :
- X lint consumer.c > consumer.lnt
- X
- X# This target is used to delete the executable and object files
- Xclean :
- X -rm $(PROGRAMS) *.o *.lnt
- END_OF_makefile
- if test 522 -ne `wc -c <makefile`; then
- echo shar: \"makefile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f run.sh -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"run.sh\"
- else
- echo shar: Extracting \"run.sh\" \(130 characters\)
- sed "s/^X//" >run.sh <<'END_OF_run.sh'
- Xecho starting consumer
- Xconsumer -i shared.dat -s 500000 -o consumer.out &
- Xsleep 3
- Xecho starting producer
- Xproducer -o shared.dat &
- END_OF_run.sh
- if test 130 -ne `wc -c <run.sh`; then
- echo shar: \"run.sh\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f producer.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"producer.c\"
- else
- echo shar: Extracting \"producer.c\" \(10418 characters\)
- sed "s/^X//" >producer.c <<'END_OF_producer.c'
- X/****producer
- X
- X Synopsis.
- X Program to produce some data and dump into a circular buffer stored in
- X shared memory (ie producer). Another process is expected to read the
- X data from the shared memory (ie consumer).
- X
- X Usage.
- X producer -o shared memory info file name
- X
- X Function.
- X
- X Routine description.
- X
- X shm_head | shm_tail | ................. |
- X
- X shm_head - will offset to the next free space
- X shm_tail - will offset to the next new data
- X Note: if shm_head = shm_tail then empty
- X
- X Notes.
- X 1) If there is no room in the shared memory circular buffer then
- X give up the time-slice to another process. In order to do this
- X call the time function which is a kernal call that will retrieve
- X the current time. After a kernal call is about to complete, the
- X operating system does a process priority scheduling check. The
- X hope here is another process will be scheduled and hopefully it
- X will be the process to read the circular buffer (ie consumer).
- X There is no guarantee it will be the desired process but it will
- X at least improve the efficiency and throughput of the system which
- X will beneficial to everyone.
- X
- X Update Log.
- X 1990 Jun 12 Robert Wolf
- X 56 Shadberry Drive
- X North York, Ontario
- X M2H 3C8 Canada
- X (416) 490-8493
- X
- X Legal Note.
- X This software is freely given to the world with the following
- X conditions:
- X 1) No change to the code and/or the comments must be done. It must be
- X distributed exactly as is. Any desired changes should be
- X sent to me and I will consider it for update.
- X 2) This software may not be published in any form with out my
- X express written consent.
- X
- X****/
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/ipc.h>
- X#include <sys/shm.h>
- X#include <string.h>
- X
- Xextern char *shmat();
- Xextern long time();
- X
- Xextern int getopt();
- Xextern char *optarg;
- X
- X#ifndef TRUE /* True */
- X#define TRUE 1
- X#endif
- X
- X#ifndef FALSE /* False */
- X#define FALSE 0
- X#endif
- X
- X#ifndef EOS /* End of string */
- X#define EOS '\0'
- X#endif
- X
- X#ifndef EOF /* End of file */
- X#define EOF (-1)
- X#endif
- X
- X#define MAX_FILE_SIZE 60 /* Maximum file name size */
- X
- Xstatic char *shm_block = (char *) NULL; /* shared memory block */
- X
- Xint main(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int shm_id; /* shared memory id */
- X int shm_size; /* shared memory size */
- X char *shm_addr; /* shared memory address selection */
- X int shm_flag; /* shared memory flags */
- X char *shm_start; /* start of shared memory */
- X long *shm_head, *shm_tail; /* head/tail offset of shared memory */
- X int avail_space; /* available space */
- X
- X static char data_string[] = "abcdefghijklmnopqrstuvwxyz0123456789\n";
- X long data_index, data_len, i;
- X
- X void die();
- X
- X data_len = strlen(data_string);
- X
- X /* Process the command line arguments */
- X if (prod_arguments(argc, argv, &shm_id, &shm_size))
- X die();
- X
- X /* Setup the signal handling */
- X if (prod_signal(die))
- X die();
- X
- X /* Attach to the shared memory data */
- X shm_addr = (char *) 0; /* allow o/s to select the address */
- X shm_flag = 0; /* read/write mode */
- X shm_block = shmat(shm_id, shm_addr, shm_flag);
- X if ((int) shm_block == (-1)) {
- X fputs("\nERROR: producer, can not attach to shared memory, ", stderr);
- X fprintf(stderr, "errno=%d\n", errno);
- X shm_block = (char *) NULL;
- X die();
- X }
- X
- X /* Setup the head and tail pointers */
- X shm_head = (long *) shm_block;
- X shm_tail = (long *) (shm_block + sizeof(long));
- X
- X shm_start = shm_block + 2L * sizeof(long);
- X
- X *shm_head = 0L;
- X *shm_tail = 0L;
- X
- X#ifdef SHM_DEBUG
- X printf("shm_block=%ld shm_start=%ld\n", shm_block, shm_start);
- X printf("shm_head =%ld *shm_head=%ld\n", shm_head, *shm_head);
- X printf("shm_tail =%ld *shm_tail=%ld\n\n", shm_tail, *shm_tail);
- X#endif
- X
- X /* Fill the shared memory continuously */
- X data_index = 0;
- X while (1) {
- X
- X /* Head pointer is ahead of tail pointer */
- X if (*shm_head >= *shm_tail) {
- X
- X avail_space = shm_size - 2L * sizeof(long) - (*shm_head) + 1L;
- X if (*shm_tail == 0L)
- X avail_space--;
- X if (avail_space <= 0L) {
- X (void) time((long *) 0); /* see note 1 above */
- X continue;
- X }
- X
- X for (i = 0L; i < avail_space; i++) {
- X shm_start[*shm_head + i] = data_string[data_index];
- X data_index = (data_index + 1) % data_len;
- X }
- X *shm_head += avail_space;
- X if (*shm_head + 2L * sizeof(long) > shm_size) /* wrap at end */
- X *shm_head = 0L;
- X
- X#ifdef SHM_DEBUG
- X printf("shm_block=%ld shm_start=%ld\n", shm_block, shm_start);
- X printf("shm_head =%ld *shm_head=%ld\n", shm_head, *shm_head);
- X printf("shm_tail =%ld *shm_tail=%ld\n", shm_tail, *shm_tail);
- X printf("num_read=%d\n\n", num_read);
- X#endif
- X
- X /* Head pointer is behind the tail pointer */
- X } else {
- X avail_space = (*shm_tail) - (*shm_head) - 1L;
- X if (avail_space <= 0L) {
- X (void) time((long *) 0); /* see note 1 above */
- X continue;
- X }
- X
- X for (i = 0L; i < avail_space; i++) {
- X shm_start[*shm_head + i] = data_string[data_index];
- X data_index = (data_index + 1) % data_len;
- X }
- X *shm_head += avail_space;
- X
- X#ifdef SHM_DEBUG
- X printf("shm_block=%ld shm_start=%ld\n", shm_block, shm_start);
- X printf("shm_head =%ld *shm_head=%ld\n", shm_head, *shm_head);
- X printf("shm_tail =%ld *shm_tail=%ld\n", shm_tail, *shm_tail);
- X printf("num_read=%d\n\n", num_read);
- X#endif
- X }
- X }
- X
- X}
- X
- X/*---------------------------------------*/
- X/* die: Terminate the program gracefully */
- X/*---------------------------------------*/
- Xstatic void die()
- X{
- X /* Deattach from shared memory */
- X if (shm_block != (char *) NULL) {
- X if (shmdt(shm_block) == (-1))
- X fprintf(stderr, "\nERROR: producer, shmdt() failed, errno=%d\n",
- X errno);
- X }
- X
- X fputs( "\nproducer: Program terminated\n", stdout);
- X
- X exit(0);
- X}
- X
- X/*----------------------------------------------------*/
- X/* prod_arguments: Process the command line arguments */
- X/* TRUE : errors detected */
- X/* FALSE : no errors */
- X/*----------------------------------------------------*/
- Xstatic int prod_arguments(argc, argv, shm_id, shm_size)
- Xint argc;
- Xchar *argv[];
- Xint *shm_id, *shm_size;
- X{
- X int ch; /* argument option */
- X int rcode; /* return code */
- X FILE *shm_info_fid; /* shared memory info file descriptor */
- X
- X void helpscreen();
- X
- X *shm_id = 0;
- X *shm_size = 0;
- X
- X rcode = FALSE;
- X do {
- X /* Get the next command line argument */
- X ch = getopt(argc, argv, "o:");
- X
- X /* Process the argument */
- X switch (ch) {
- X
- X case EOF: /* no more arguments */
- X break;
- X
- X case 'o': /* shared memory information filename */
- X shm_info_fid = fopen(optarg, "r");
- X if (shm_info_fid == (FILE *) NULL) {
- X fprintf(stdout, "\nCan not open info file '%s'\n", optarg);
- X rcode = TRUE;
- X break;
- X }
- X
- X if (fscanf(shm_info_fid, "%d%d", shm_id, shm_size) != 2) {
- X fputs("\nCan not parse info file\n", stdout);
- X rcode = TRUE;
- X break;
- X }
- X
- X if (fclose(shm_info_fid) != 0) {
- X fputs("\nCan not close info file\n", stdout);
- X rcode = TRUE;
- X }
- X break;
- X
- X case '?': /* error */
- X helpscreen();
- X rcode = TRUE;
- X break;
- X
- X default : /* safety net */
- X break;
- X }
- X } while (ch != EOF);
- X
- X /* Check the shared memory info file name was specified */
- X if ((!rcode) && (*shm_id <= 0 || *shm_size <= 0)) {
- X helpscreen();
- X fprintf(stderr, "\nERROR: Missing -o parameter\n");
- X rcode = TRUE;
- X }
- X
- X return (rcode);
- X
- X}
- X
- X/*--------------------------------------------------*/
- X/* helpscreen: Display a help message on the screen */
- X/*--------------------------------------------------*/
- Xstatic void helpscreen()
- X{
- X fputc('\n', stderr);
- X fputs("ERROR: Invalid usage: producer\n", stderr);
- X fputs(" -o shared memory info file name\n", stderr);
- X}
- X
- X/*---------------------------------------------------*/
- X/* prod_signal: Sets up the handling of all signals. */
- X/* TRUE : errors detected */
- X/* FALSE : no errors */
- X/*---------------------------------------------------*/
- Xstatic int prod_signal(sig_function)
- Xvoid (*sig_function)();
- X{
- X void (*sig_handle)(); /* signal handler */
- X
- X sig_handle = signal(SIGINT, sig_function);
- X if ((int) sig_handle == (-1)) {
- X fprintf(stderr, "\nERROR: signal(SIGINT) fails, errno=%d\n", errno);
- X return (TRUE);
- X }
- X
- X sig_handle = signal(SIGQUIT, sig_function);
- X if ((int) sig_handle == (-1)) {
- X fprintf(stderr, "\nERROR: signal(SIGQUIT) fails, errno=%d\n", errno);
- X return (TRUE);
- X }
- X
- X sig_handle = signal(SIGHUP, sig_function);
- X if ((int) sig_handle == (-1)) {
- X fprintf(stderr, "\nERROR: signal(SIGHUP) fails, errno=%d\n", errno);
- X return (TRUE);
- X }
- X
- X sig_handle = signal(SIGTERM, sig_function);
- X if ((int) sig_handle == (-1)) {
- X fprintf(stderr, "\nERROR: signal(SIGTERM) fails, errno=%d\n", errno);
- X return (TRUE);
- X }
- X
- X return (FALSE);
- X}
- END_OF_producer.c
- if test 10418 -ne `wc -c <producer.c`; then
- echo shar: \"producer.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f consumer.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"consumer.c\"
- else
- echo shar: Extracting \"consumer.c\" \(13115 characters\)
- sed "s/^X//" >consumer.c <<'END_OF_consumer.c'
- X/****consumer
- X
- X Synopsis.
- X Program to read a circular buffer stored in shared memory.
- X Another process is expected to write the data into the shared memory
- X (ie producer).
- X
- X Usage.
- X consumer -i shared memory info file name -s shared memory size
- X -o output file name
- X
- X Function.
- X
- X Routine description.
- X
- X shm_head | shm_tail | ................. |
- X
- X shm_head - will offset to the next free space
- X shm_tail - will offset to the next new data
- X Note: if shm_head = shm_tail then empty
- X
- X Notes.
- X 1) If there is no data in the shared memory circular buffer then
- X give up the time-slice to another process. In order to do this
- X call the time function which is a kernal call that will retrieve
- X the current time. After a kernal call is about to complete, the
- X operating system does a process priority scheduling check. The
- X hope here is another process will be scheduled and hopefully it
- X will be the process to write into the circular buffer (ie producer).
- X There is no guarantee it will be the desired process but it will
- X at least improve the efficiency and throughput of the system which
- X will beneficial to everyone.
- X
- X Update Log.
- X 1990 Jun 12 Robert Wolf
- X 56 Shadberry Drive
- X North York, Ontario
- X M2H 3C8 Canada
- X (416) 490-8493
- X
- X Legal Note.
- X This software is freely given to the world with the following
- X conditions:
- X 1) No change to the code and/or the comments must be done. It must be
- X distributed exactly as is. Any desired changes should be
- X sent to me and I will consider it for update.
- X 2) This software may not be published in any form with out my
- X express written consent.
- X
- X****/
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <fcntl.h>
- X#include <errno.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/ipc.h>
- X#include <sys/shm.h>
- X
- Xextern char *shmat();
- Xextern long time();
- Xextern int getopt();
- Xextern char *optarg;
- X
- X#ifndef TRUE /* True */
- X#define TRUE 1
- X#endif
- X
- X#ifndef FALSE /* False */
- X#define FALSE 0
- X#endif
- X
- X#ifndef EOS /* End of string */
- X#define EOS '\0'
- X#endif
- X
- X#ifndef EOF /* End of file */
- X#define EOF (-1)
- X#endif
- X
- X#define MAX_FILE_SIZE 60 /* Maximum file name size */
- X#define MIN_SHM_SIZE (2L * sizeof(long) + 8L) /* min. shared memory size */
- X
- Xstatic int shm_id = (-1); /* shared memory id */
- Xstatic char *shm_block = (char *) NULL; /* shared memory block */
- X
- Xstatic char shm_info_fname[MAX_FILE_SIZE+1]; /* shared memory info file name */
- X
- Xint main(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int shm_size; /* shared memory size */
- X char output_fname[MAX_FILE_SIZE+1]; /* output file name */
- X int output_fid; /* output file descriptor */
- X FILE *shm_info_fid; /* shared memory info file desc. */
- X int shm_perm; /* shared memory permissions */
- X int shm_flags; /* shared memory operation flags */
- X int shm_key; /* shared memory key */
- X int num_written; /* number of bytes written */
- X char *shm_addr; /* shared memory address selection */
- X int shm_aflags; /* shared memory attaching flags */
- X char *shm_start; /* start of shared memory */
- X long *shm_head, *shm_tail; /* head/tail offsets of shared memory */
- X int avail_data; /* available data */
- X
- X void die();
- X
- X /* Process the command line arguments */
- X if (cons_arguments(argc, argv, &shm_size, output_fname))
- X
- X die();
- X
- X /* Setup the signal handling */
- X if (cons_signal(die))
- X die();
- X
- X /* Open the output file */
- X if (output_fname[0] == EOS)
- X output_fid = 1; /* ie standard output */
- X else {
- X output_fid = open(output_fname, O_WRONLY);
- X if (output_fid == (-1))
- X output_fid = creat(output_fname, S_IRUSR | S_IWUSR);
- X if (output_fid < 0) {
- X fprintf(stderr, "\nERROR: Can not open output file : %s\n",
- X output_fname);
- X die();
- X }
- X }
- X
- X /* Create the shared memory segment */
- X shm_perm = SHM_R | SHM_W |
- X (SHM_R >> 3) | (SHM_W >> 3) |
- X (SHM_R >> 6) | (SHM_W >> 6);
- X shm_flags = IPC_CREAT | IPC_EXCL | shm_perm;
- X shm_key = 1;
- X do {
- X shm_id = shmget(shm_key, shm_size, shm_flags);
- X if (shm_id == (-1)) {
- X if (errno != EEXIST) {
- X fputs("\nconsumer: ERROR: shmget(), failed, ", stderr);
- X fprintf(stderr, "errno=%d\n", errno);
- X die();
- X }
- X shm_key++;
- X }
- X } while (shm_id == (-1));
- X
- X /* Attach to the shared memory data */
- X shm_addr = (char *) 0; /* allow o/s to select the address */
- X shm_aflags = 0; /* read/write mode */
- X shm_block = shmat(shm_id, shm_addr, shm_aflags);
- X if ((int) shm_block == (-1)) {
- X fputs("\nERROR: consumer, can not attach to shared memory, ", stderr);
- X fprintf(stderr, "errno=%d\n", errno);
- X shm_block = (char *) NULL;
- X die();
- X }
- X
- X /* Output the shared memory id and shared memory size */
- X /* to the shared memory informatio file */
- X shm_info_fid = fopen(shm_info_fname, "w");
- X if (shm_info_fid == (FILE *) NULL) {
- X fputs("\nERROR: Could not open shared memory info file, ", stderr);
- X fprintf(stderr, "errno=%d\n", errno);
- X die();
- X }
- X
- X fprintf(shm_info_fid, "%d %d\n", shm_id, shm_size);
- X
- X if (fclose(shm_info_fid) != 0) {
- X fputs("\nERROR: Could not open shared memory info file, ", stderr);
- X fprintf(stderr, "errno=%d\n", errno);
- X die();
- X }
- X
- X /* Setup the head and tail pointers */
- X shm_head = (long *) shm_block;
- X shm_tail = (long *) (shm_block + sizeof(long));
- X
- X shm_start = shm_block + 2L * sizeof(long);
- X
- X *shm_head = 0L;
- X *shm_tail = 0L;
- X
- X#ifdef SHM_DEBUG
- X printf("shm_block=%ld shm_start=%ld\n", shm_block, shm_start);
- X printf("shm_head =%ld *shm_head=%ld\n", shm_head, *shm_head);
- X printf("shm_tail =%ld *shm_tail=%ld\n\n", shm_tail, *shm_tail);
- X#endif
- X
- X /* Read the port continuously */
- X while (1) {
- X
- X /* Tail pointer is equal to head pointer */
- X if (*shm_tail == *shm_head)
- X (void) time((long *) 0); /* see note 1 above */
- X
- X /* Tail pointer is behind of head pointer */
- X else if (*shm_tail < *shm_head) {
- X avail_data = (*shm_head) - (*shm_tail);
- X num_written = write(output_fid, shm_start + (*shm_tail),
- X avail_data);
- X if (num_written != avail_data) {
- X fprintf(stderr, "\nERROR: consumer: write() failed, errno=%d\n",
- X errno);
- X die();
- X }
- X *shm_tail += avail_data;
- X
- X /* Tail pointer is ahead of head pointer */
- X } else {
- X avail_data = shm_size - 2L * sizeof(long) - (*shm_tail) + 1L;
- X num_written = write(output_fid, shm_start + *shm_tail, avail_data);
- X if (num_written != avail_data) {
- X fprintf(stderr, "\nERROR: consumer: write() failed, errno=%d\n",
- X errno);
- X die();
- X }
- X *shm_tail = 0L;
- X }
- X
- X }
- X
- X}
- X
- X/*---------------------------------------*/
- X/* die: Terminate the program gracefully */
- X/*---------------------------------------*/
- Xstatic void die()
- X{
- X /* Delete the shared memory info file */
- X if (shm_info_fname[0] != EOS)
- X unlink(shm_info_fname);
- X
- X /* Deattach from shared memory */
- X if (shm_block != (char *) NULL) {
- X if (shmdt(shm_block) == (-1))
- X fprintf(stderr, "\nERROR: consumer, shmdt() failed, errno=%d\n",
- X errno);
- X }
- X
- X /* Remove the shared memory entity */
- X if (shm_id != (-1)) {
- X if (shmctl(shm_id, IPC_RMID, 0) == (-1))
- X fprintf(stderr, "\nERROR: consumer, shmctl() failed, errno=%d\n",
- X errno);
- X }
- X
- X fputs( "\nconsumer: Program terminated\n", stdout);
- X
- X exit(0);
- X}
- X
- X/*----------------------------------------------------*/
- X/* cons_arguments: Process the command line arguments */
- X/* TRUE : errors detected */
- X/* FALSE : no errors */
- X/*----------------------------------------------------*/
- Xstatic int cons_arguments(argc, argv, shm_size, output_fname)
- Xint argc;
- Xchar *argv[];
- Xint *shm_size;
- Xchar output_fname[];
- X{
- X int ch; /* argument option */
- X int rcode; /* return code */
- X
- X static char msg_too_big[] = "\nERROR: -%c parameter is too large\n";
- X static char msg_invalid[] = "\nERROR: -%c parameter invalid value\n";
- X static char msg_missing[] = "\nERROR: Missing -%c parameter\n";
- X
- X void helpscreen();
- X
- X shm_info_fname[0] = EOS;
- X *shm_size = 0;
- X output_fname[0] = EOS;
- X
- X rcode = FALSE;
- X do {
- X /* Get the next command line argument */
- X ch = getopt(argc, argv, "i:s:o:");
- X
- X /* Process the argument */
- X switch (ch) {
- X
- X case EOF: /* no more arguments */
- X break;
- X
- X case 'i': /* shared memory info file name */
- X if (strlen(optarg) > MAX_FILE_SIZE) {
- X fprintf(stderr, msg_too_big, ch);
- X rcode = TRUE;
- X } else
- X strcpy(shm_info_fname, optarg);
- X break;
- X
- X case 's': /* shared memory size */
- X if (sscanf(optarg, "%d", shm_size) != 1 ||
- X *shm_size < MIN_SHM_SIZE) {
- X fprintf(stderr, msg_invalid, ch);
- X rcode = TRUE;
- X break;
- X }
- X
- X break;
- X
- X case 'o': /* output file name */
- X if (strlen(optarg) > MAX_FILE_SIZE) {
- X fprintf(stderr, msg_too_big, ch);
- X rcode = TRUE;
- X } else
- X strcpy(output_fname, optarg);
- X break;
- X
- X case '?': /* error */
- X helpscreen();
- X rcode = TRUE;
- X break;
- X
- X default : /* safety net */
- X break;
- X }
- X } while (ch != EOF);
- X
- X /* Check the shared memory info file name was specified */
- X if ((!rcode) && shm_info_fname[0] == EOS) {
- X helpscreen();
- X fprintf(stderr, msg_missing, 'i');
- X rcode = TRUE;
- X }
- X
- X /* Check the shared memory size was specified */
- X if ((!rcode) && *shm_size <= 0) {
- X helpscreen();
- X fprintf(stderr, msg_missing, 's');
- X rcode = TRUE;
- X }
- X
- X return (rcode);
- X
- X}
- X
- X/*--------------------------------------------------*/
- X/* helpscreen: Display a help message on the screen */
- X/*--------------------------------------------------*/
- Xstatic void helpscreen()
- X{
- X fputc('\n', stderr);
- X fputs("ERROR: Invalid usage: consumer\n", stderr);
- X fputs(" -i shared memory info file name\n", stderr);
- X fputs(" -s shared memory size\n", stderr);
- X fputs(" -o output file name\n", stderr);
- X}
- X
- X/*---------------------------------------------------*/
- X/* cons_signal: Sets up the handling of all signals. */
- X/* TRUE : errors detected */
- X/* FALSE : no errors */
- X/*---------------------------------------------------*/
- Xstatic int cons_signal(sig_function)
- Xvoid (*sig_function)();
- X{
- X void (*sig_handle)(); /* signal handler */
- X
- X sig_handle = signal(SIGINT, sig_function);
- X if ((int) sig_handle == (-1)) {
- X fprintf(stderr, "\nERROR: signal(SIGINT) fails, errno=%d\n", errno);
- X return (TRUE);
- X }
- X
- X sig_handle = signal(SIGQUIT, sig_function);
- X if ((int) sig_handle == (-1)) {
- X fprintf(stderr, "\nERROR: signal(SIGQUIT) fails, errno=%d\n", errno);
- X return (TRUE);
- X }
- X
- X sig_handle = signal(SIGHUP, sig_function);
- X if ((int) sig_handle == (-1)) {
- X fprintf(stderr, "\nERROR: signal(SIGHUP) fails, errno=%d\n", errno);
- X return (TRUE);
- X }
- X
- X sig_handle = signal(SIGTERM, sig_function);
- X if ((int) sig_handle == (-1)) {
- X fprintf(stderr, "\nERROR: signal(SIGTERM) fails, errno=%d\n", errno);
- X return (TRUE);
- X }
- X
- X return (FALSE);
- X}
- END_OF_consumer.c
- if test 13115 -ne `wc -c <consumer.c`; then
- echo shar: \"consumer.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of shell archive.
- exit 0
-