Homework 7: a portable inter-process messaging library

Modern operating systems provide several means of inter-process communication. In linux, these include signals, pipes, System V IPC and posix queues, shared memory and semaphores, UNIX and Internet sockets, and mmap() shared memory.

In this homework, we build our own inter-process messaging library using some of these underlying mechanisms. Using the preprocessor, we write code that works whether or not various different underlying mechanisms are available on our current system.

The listing below describes the public API of our messaging library.

%CODE{ lang="c" }% /* returns a mailbox descriptor, or -1 on failure */ int open_mailbox();

/* Reliably delivers the provided message to exactly one process that reads from the mailbox. If no process is currently waiting for a message, the message is queued for later. Returns immediately unless queue is full, in which case it blocks. */ void send_msg(int mailbox, char* msg, int len);

/* blocks until a message is received. */ int receive_msg(int mailbox, char* buf, int max_len);

%ENDCODE%

The homework template contains an implementation of the above API using POSIX Message Queues. Message queues implement essentially the same semantics described above, making the implementation pretty straightforward. Your job is to provide the same service without using message queues.

Turn-in requirements: put all your code in the file hw7.c (and hw7.h if you want), making no changes to server.c or client.c.

Message Queues using POSIX shared memory and semaphores

In this part, POSIX queues may no longer be available. Surround your POSIX queue-specific code with #ifdef POSIX_QUEUES preprocessor directives, so that your program uses POSIX queues when compiled with gcc -DPOSIX_QUEUES, but does not use the queues otherwise.

When POSIX queues are unavailable, implement the same functionality using POSIX shared memory and semaphores. The template code contains a beginning of the shared memory solution, but without synchronization and without queueing.

sem.c holds a short semaphore example. Use a named semaphore to synchronize access to the shared memory, and add a queue to handle buffering of messages sent early. Use a semaphore initialized to 0 to make servers wait until the queue has a message for them.

Message Queues using the file system, flock() and signals

Sometimes, shared memory and memory mapping may not be available either. use an #ifdef POSIX_SHM directive, and if shared memory is not available, fall back on using the file system for communication.

Use flock() for process synchronization, and read and write the contents of files using read() write() and lseek() for message passing. You may need to use fsync() to force writing data to disk. Use signals ( kill()) to wake up processes waiting for messages.

Topic revision: r7 - 2011-03-03 - 23:04:42 - Main.jakob
 
Copyright 2016 The Board of Trustees
of the University of Illinois.webmaster@cs.uic.edu
WISEST
Helping Women Faculty Advance
Funded by NSF