Lab 4 — System V IPC: Shared Memory & Message Queues

CMPS 3600 • Fall 2025

Overview

This lab introduces two System V IPC mechanisms: shared memory and message queues. You will write a parent/child program where the parent sends an integer via shared memory and a string via a message queue.

Background: SysV IPC is a portable way to communicate among related (parent/child) and unrelated processes. If multiple processes touch the same memory location, synchronization is required (typically via semaphores—covered later in the course). For this lab, we’ll rely on a simple busy‑wait and careful ordering to keep things deterministic.

Resources

Step 1 — Setup

$ cd ~
$ cd cs3600
$ ./lab-start.sh
$ cd 4
$ cp /home/fac/dfanucchi/public_html/cs3600/examples/4/*.c .
$ cp /home/fac/dfanucchi/public_html/cs3600/examples/4/Makefile .
$ cp /home/fac/dfanucchi/public_html/cs3600/examples/4/cleanipc.sh .

Read each example, compile, and run it. When comfortable, begin dflab4.c.

Pro tip: If your program crashes, remove IPC objects before re‑running:
$ ./cleanipc.sh <username>	#this is a script that should do the clean up for you

# to view and remove your IPC objects manually, use the following commands:
$ ipcs -m    # shared memory
$ ipcs -q    # message queues
$ ipcrm -m <shmid>
$ ipcrm -q <msqid>

Step 2 — Assignment (dflab4.c)

Create the dflab4.c file, it is not included this week.

Required headers:
# this is not an exhaustive list, you need to list the remaining headers

#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>

Before fork()

  1. Generate IPC key from a sentinel file foo:
    $ cd ~/cs3600/4
    $ touch foo
    Use ftok("foo", 17).
  2. Open a log file for writing (child will write; open before fork()).
  3. Create shared memory, attach, initialize to 0.
  4. Create message queue using the same key; define a message struct and type.
Shared memory skeleton
key_t ipckey = ftok("foo", 17);
int shmid = shmget(ipckey, sizeof(int), IPC_CREAT | 0666);
int *shared = (int*)shmat(shmid, NULL, 0);
*shared = 0;
Message queue skeleton
struct msg { long mtype; char text[128]; };
int msqid = msgget(ipckey, IPC_CREAT | 0666);

Call fork()

Child

  1. Busy‑wait until *shared != 0 (with a small sleep):
    while (*shared == 0) {
      usleep(4250);   /* 4.25ms */
    }
  2. Write the integer to log.
  3. Block on msgrcv() for a word from parent; write it to log.
  4. Close log, detach from shared memory, exit(0).
    Parent performs IPC cleanup after wait().

Parent

  1. Prompt and read a two‑digit integer; convert and store in shared memory:
    write(1, "Enter a 2-digit number: ", 24);
    char buf[128]; memset(buf, 0, sizeof(buf));
    read(0, buf, 4);            // read up to 4 chars
    int num = atoi(buf);
    *shared = num;
  2. Note on buffers: You always need a buffer when reading input. A buffer is a block of memory where the characters typed are stored before being processed. Without it, you can’t control how many characters are accepted, you risk overwriting memory (buffer overflow), and you lose the ability to clear/reset input between reads. For this lab, define a buffer large enough (e.g., #define BUFSIZE 256) so it can safely hold both the number and the word you’ll read from the user. Always memset() the buffer before reuse.
  3. Prompt and read a word; send via msgsnd() to the queue.
  4. wait(&status) to reap the child; print exit status.
  5. Cleanup: shmdt(shared), shmctl(shmid, IPC_RMID, 0), msgctl(msqid, IPC_RMID, 0).
Ordering matters: Create the IPC key before the fork so both processes share the same key. The child inherits the attached shared memory pointer; a second shmat() is unnecessary.

Build & Run

$ make
$ ./dflab4
Enter a two-digit number: 75
Enter a word: Linuxize
Child exited with status code 0

$ cat log
75
Linuxize

Run with an input file (myinput)

myinput
# myinput
83
System-V
$ ./dflab4 < myinput
$ cat log
83
System-V
Input file note: When using redirection, read() may consume bytes from the next line. Adjust the read count and/or clear the buffer each time.

Trace with strace (IPC only)

$ strace -f -e trace=ipc ./dflab4 < myinput

shmget(0x1102af98, 4, IPC_CREAT|0666)   = 911605760
shmat(911605760, 0, 0)                  = 0x7fac33f01000
msgget(0x1102af98, IPC_CREAT|0666)      = 297172992
Process 9356 attached
[pid  9355] msgsnd(297172992, {1, "System-V\n..."}, 112, 0) = 0
[pid  9356] msgrcv(297172992, {1, "System-V\n..."}, 112, 0, 0) = 112
[pid  9356] shmdt(0x7fac33f01000)       = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
shmdt(0x7fac33f01000)                   = 0
msgctl(297172992, IPC_RMID, 0)          = 0
shmctl(911605760, IPC_RMID, 0)          = 0

Files to be collected:

Cleanup required: Verify no IPC objects remain (ipcs -m, ipcs -q); remove leftovers with ipcrm -m <shmid>, ipcrm -q <msqid> or run ./cleanipc.sh <username>.