Inter-Process Communicatio N: Tanzir Ahmed CSCE 313 Fall 2018
Inter-Process Communicatio N: Tanzir Ahmed CSCE 313 Fall 2018
COMMUNICATIO
N
Tanzir Ahmed
CSCE 313 Fall 2018
Inter-Process Communication
■ IPC Methos
– Pipes and FIFO
– Message Passing
– Shared Memory
– Semaphore Sets
– Signals
■ References:
– Beej’s guide to Inter Process Communication for the code examples
(https://beej.us/guide/bgipc/)
– Understanding Unix/Linux Programming, Bruce Molay, Chapters 10, 15
– Advanced Linux Programming Ch 5
– Some material also directly taken or adapted with changes from
Illinois course in System Programming (Prof. Angrave), UCSD (Prof. Snoeren),
and USNA (Prof. Brown)
Inter-Process Communication
■ A process contains everything needed for execution
– An address space (defining all the code and data)
– OS resources (e.g., open files) and accounting information
– Execution state (PC, SP, registers, etc.)
– Each of these resources is exclusive to the process
■ Yet sometimes processes may wish to cooperate (information sharing,
performance, modularity, etc.)
– But how to communicate? Each process is an island
– The OS needs to intervene to bridge the gap
– OS provides system calls to support Inter-Process Communication
(IPC)
Inter-Process Communication
■ OS provides generic mechanisms to communicate
– Un-named and Named Pipes
■ Explicit communication channel
■ Explicit Synchronization: read() operation is blocking
Process has some usual files open Kernel creates a pipe and sets file descriptors
■ BEFORE
– Shows standard set of file descriptors
AFTER
Shows newly created pipe in the kernel and the two connections to that pipe in
the process
IPC Pipe - Method
int main ()
{
int fds [2]; child
pipe (fds); // connect the pipe
if (!fork()){ // on the child side
sleep (3);
char * msg = "a test message";
printf ("CHILD: Sent %s\n", msg);
write (fds [1], msg, strlen(msg)
+1);
}else{
char buf [100]; parent
read (fds [0], buf, 100);
printf ("PRNT: Recvd %s\n", buf);
}
return 0;
}
Shell Piping: “ls -l|wc –l”
void main ()
{
int fds [2];
pipe (fds); // connect the pipe
if (!fork()){ // on the child side
close (fds[0]); // closing unnecessary pipe end
dup2 (fds[1], 1); // overwriting stdout with pipeout
execlp ("ls", "ls", "-l", NULL);
}else{
close (fds[1]); // closing unnecessary pipe end
dup2 (fds[0], 0); // overwrite stdin with pipe in
execlp ("wc", "wc", "-l", NULL);
}
}
IPC- FIFO (named PIPE)
FIFO
■ A pipe (also called unnamed pipe) disappears when no process has it open
■ FIFOs (also called named pipes) are a mechanism that allow for IPC that's
similar to using regular files, except that the kernel takes care of
synchronizing reads and writes, and
■ Data is never actually written to disk (instead it is stored in buffers in
memory) so the overhead of disk I/O (which is huge!) is avoided.
FIFO vs PIPE
■ A FIFO is like an unconnected garden hose lying on the lawn
– Anyone can put one end of the hose to his ear and another
person can walk up to the hose and speak into the other end
– Unrelated people may communicate through a hose
– Hose exists even if nobody is using it
FIFO
■ It’s part of the file system
– It has a name and path just like a regular file.
– Programs can open it for reading and writing, just like a regular file.
– However, the name is simply a convenient reference for what is
actually just a stream of bytes - no persistent storage or ability to move
backwards of jump forward in the stream.
■ Works like a Bounded Buffer
– Bytes travel in First-In-First-Out fashion: hence the name FIFO.
– If a read is performed on a FIFO and the writer has not yet written a
byte, the kernel actually puts the reading process to sleep until data is
available to read.
– If the writer has written so much data that the FIFO's buffer is full, it
is put to sleep until some reader process has read some bytes
FIFO - Problems
■ We still need to agree on a name ahead of time – how to
communicate that??
RequestChannel*rc = new
RequestChannel(“control”, ..){
…
mkfifo (“control”,
PERMS); // create
}
■ Not concurrency safe within a process
– Like a file used by multiple processes/threads
– Multiple threads writing can cause race condition
Using FIFO’s
■ How do I create a FIFO
– mkfifo (name)
■ How do I remove a FIFO
– rm fifoname or unlink(fifoname)
■ How do I listen at a FIFO for a connection
– open (fifoname, O_RDONLY)
■ How do I open a FIFO in write mode?
– open(fifoname, O_WRONLY)
■ How do two processes speak through a FIFO?
– The sending process uses write and the listening process
uses read. When the writing process closes, the reader sees
end of file
FIFO DEMO
Writer
#define FIFO_NAME "test.txt"
int main(void)
{ Reader
char s[300];
int main(void)
int num, fd;
{
mkfifo(FIFO_NAME, 0666); // create
char s[300];
printf("Waiting for readers...\n");
int num, fd;
fd = open(FIFO_NAME, O_WRONLY); //open
printf("waiting for writers...\n");
if (fd < 0)
fd = open(FIFO_NAME, O_RDONLY);
return 0;
printf("got a writer\n");
printf("Got a reader--type some stuff\
do{
n");
if ((num = read(fd, s, 300)) == -1)
while (gets(s)) {
perror("read");
if (!strcmp (s, "quit")) break;
else {
if ((num = write(fd, s, strlen(s)))
s[num] = '\0';
== -1)
printf("RECV: read %d
perror("write");
bytes: \"%s\"\n", num, s);
else
}
printf("SENDER: wrote %d bytes\n",
} while (num > 0);
num);
return 0;
}
}
//unlink (FIFO_NAME);
return 0;
}
IPC: Message Passing
Message Passing
Process P2
Process P1 Mailbox A
Process P3
Indirect Message Passing
■ Operations
– create a new mailbox
– send and receive messages through mailbox
– destroy a mailbox
■ Primitives are defined as:
send(A, message) – send a message to mailbox A
receive(A, message) – receive a message from mailbox A
Process P2
Process P1 Mailbox A
Process P3
Synchronization
■ Message passing may be either blocking or non-blocking
■ Blocking is considered synchronous
– Blocking send has the sender block until the message is
received
– Blocking receive has the receiver block until a message is
available
■ Non-blocking is considered asynchronous
– Non-blocking send has the sender send the message and
continue
– Non-blocking receive has the receiver receive a valid message
or null
Buffering
■ Queue of messages attached to the link; implemented in one of
three ways
1. Zero capacity – 0 messages
Sender must wait for receiver (rendezvous)
2. Bounded capacity – finite length of n messages
Sender must wait if link full
3. Unbounded capacity – infinite length
Sender never waits
IPC Object Creation: Message
Queues Object key identifies object across processes. Can be assigned
as follows:
-- Create some unknown key
-- Pass explicit key (beware of collisions!)
-- Use file system to consistently hash key (using ftok)
#include <sys/msg.h>
msgtyp action
0 remove first message from queue
> 0 remove first message of type msgtyp from the queue
< 0 remove first message of lowest type that is less than
or equal to absolute value of msgtyp
Operations on Message
Queues (cont.)
int msgctl(int msqid, int cmd, struct msgid_ds *buf)
Cmd description
IPC_RMID remove the message queue msqid and destroy the
corresponding msqid_ds
IPC_SET Set members of the msqid_ds data structure from
buf
IPC_STAT Copy members of the msqid_ds data structure into
buf
Message Queue – Example
struct my_msgbuf {
long mtype;
char mtext[200];
};
int sender(void)
{
struct my_msgbuf buf;
int msqid = msgget(654321, 0644 | IPC_CREAT); // create the
msg queue
while(fgets(buf.mtext, sizeof buf.mtext, stdin) != NULL) {
int len = strlen(buf.mtext);
msgsnd(msqid, &buf, len+1, 0);
}
msgctl(msqid, IPC_RMID, NULL); // delete the msg queue
}
int receiver(void)
{
struct my_msgbuf buf;
int msqid = msgget(654321, 0644); // connect (not create)
while(1) {
msgrcv(msqid, &buf, sizeof buf.mtext, 0, 0);
IPC: Shared Memory
Shared Memory
■ How does data travel through a FIFO?
– ‘write’ copies data from process memory to kernel buffer
and then ‘read’ copies data from a kernel buffer to process
memory
■ If both processes are on the same machine living in different
parts of user space, then they may not need to copy data in and
out of the kernel
– They may exchange or share data by using a shared
memory segment
– Shared memory is to processes what global variables are to
threads
Shared Memory
■ Processes share the same segment of memory directly
– Memory is mapped into the address space of each sharing
process
– Memory is persistent beyond the lifetime of the creating or
modifying processes (until deleted)
■ But, now the processes are on their own for synchronization
– Mutual exclusion must be provided by processes using the
shared memory
– Semaphores – to ensure Producer-Consumer relation also
has to be now done by the respective processes
Shared Memory
Process A Process B
OS Address Space
#include <sys/shm.h>