0% found this document useful (0 votes)
44 views44 pages

Inter-Process Communicatio N: Tanzir Ahmed CSCE 313 Fall 2018

This document discusses various methods of inter-process communication (IPC) including pipes, FIFOs, message passing, and shared memory. Pipes allow for unidirectional communication between related processes using file descriptors. FIFOs are similar to pipes but use named pipes that exist as files in the file system. Message passing involves processes explicitly sending and receiving messages through communication channels like mailboxes. Shared memory allows processes to read and write the same memory address space.

Uploaded by

drkhamuruddeen
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views44 pages

Inter-Process Communicatio N: Tanzir Ahmed CSCE 313 Fall 2018

This document discusses various methods of inter-process communication (IPC) including pipes, FIFOs, message passing, and shared memory. Pipes allow for unidirectional communication between related processes using file descriptors. FIFOs are similar to pipes but use named pipes that exist as files in the file system. Message passing involves processes explicitly sending and receiving messages through communication channels like mailboxes. Shared memory allows processes to read and write the same memory address space.

Uploaded by

drkhamuruddeen
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 44

INTER-PROCESS

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

– Message Passing: explicit communication channel provided through


send()/receive() system calls
■ Explicit Synchronization through send() and recv()

– Shared Memory: multiple processes can read/write same physical


portion of memory; implicit channel
■ Implicit channel
■ No OS mediation required once memory is mapped
■ No synchronization between communicating threads
– There is no read/send or write/recv available
– How to know when data is available?
IPC Fundamental
Communication Models

Example: pipe, fifo, message, Example: shared memory, memory


signal mapped file
Communication Over a Pipe
Unix Pipes (aka Unnamed Pipes)
int pipe(int fildes[2])
■ Returns a pair of file descriptors
– fildes[0] is connected to the read end of the pipe
– fildes[1] is connected to the write end of the pipe
■ Create a message pipe
– Data is received in the order it was sent
– OS enforces mutual exclusion: only one process at a
time
– Processes sharing the pipe must have same parent
in common
Pipe Creation
BEFORE pipe AFTER pipe

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

Connects the two


fds as pipe

■ Is this of any use at all ???


Unnamed Pipe Between Two Processes

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

■ Mechanism for processes to communicate and to


synchronize their actions
■ IPC facility provides two operations:
– send(message)
– receive(message)
■ If P and Q wish to communicate, they need to:
– establish a communication link between them
– exchange messages via send/receive
Message Passing
Direct Message Passing
■ Processes must name each other explicitly:
– send (P, message) – send a message to process P
– receive(Q, message) – receive a message from process Q
■ Properties of communication link
– Links are established automatically (or implicitly) while
sending/receiving
– A link is associated with exactly one pair of communicating
processes
– Between each pair, there exists exactly one link
■ Limitation: Must know the name or id of the other process
Process A Process B
Indirect Message Passing
■ Messages are directed to and received from mailboxes (also referred to
as ports)
– Mailbox can be owned by a process or by the OS
– Each mailbox has a unique id
– Processes can communicate only if they share a mailbox
■ Properties of communication link
– Link established only if processes share a common mailbox
– A link may be associated with many processes
– Each pair of processes may share several communication links

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>

int msgget(key_t key, int msgflg);


/* create a message queue with given key and flags. */
key_t ftok(const char *path, int id);
/* path is an accessible file, id is any
integer, works like a seed in a random num
generator. */
Object id is similar to file descriptor.
-- It can be inherited across fork() calls.
Operations on Message
Queues #define PERMS (S_IRUSR | S_IWUSR)
int msqid;
if ((msqid = msgget(key, PERMS)) == -1)
perror(“msgget failed);
struct mymsg { /* user defined! */
long msgtype; /* first field must be a long identifier */
char mtext[1]; /* placeholder for message content */
}
int msgsnd(int msqid, const void *msgp,
size_t msgsz, int msgflg)

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz,


long msgtyp, int msgflg);

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

■ Processes request the segment


■ OS maintains the segment
■ Processes can attach/detach the segment
Facts about Shared Memory
Segments
■ A shared memory segment has a name, called a key,
which is an integer
■ A shared memory segment has an owner and
permission bits
■ Processes may “attach” or “detach” a segment,
obtaining a pointer to the segment
■ reads and writes to the memory segment are done via
regular pointer operations
Shared Memory – POSIX
functions
■ shmget: create and initialize or access
■ shmat: attach memory to process
■ shmdt: detach memory from process
■ shmctl: control
POSIX Shared Memory

#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

Ok, we have created a shared-memory segment. Now what?

void *shmat(int shmid, const void *shmaddr,


int shmflg);
address space of
calling process
P1
address space of
shared-memory system memory calling process
segment mapped by P2
shmat
shared-memory
segment created by shared-memory
shmget segment mapped by
shmat
Shared Memory Example
void send(char *msg){
/* Create the segment: */
int shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT);
/* attach to the segment to get a pointer to it: */
data = shmat(shmid, 0, 0);
/* modify segment by copying a string msg into it */
printf("writing to segment: \"%s\"\n", argv[1]);
strncpy(data, argv[1], SHM_SIZE);
/* detach from the segment: */
shmdt(data);
}
char* recv (){
/* connecting to the segment: */
int shmid = shmget(key, SHM_SIZE, 0644);
/* attach to the segment to get a pointer to it: */
data = shmat(shmid, 0, 0);
return data;
}
Shared Memory - Summary
■ It’s great because it does not allocate extra memory
– 3-times less memory (In others you have 1 copy in kernel, 2
others in the individual processes)
■ But a huge problem looms
– Who does synchronization?
– There is no guarantee of order between sending and
receiving processes
– The receiver process can run first finding nothing or stale
data in the buffer
Kernel Semaphores

■ We have learned how to synchronize multiple threads using


Semaphores and Locks
■ But how do we synchronize multiple processes?
– We will again need semaphores, but this time Kernel
Semaphores
– They are visible to separate processes who do not share
address space

int semget(key_t key, int nsem, int flags);


/* create a “Semaphore Set” with given key and flags.
*/
takes an array (and also its size),
Kernel Semaphores because remember we are working
with a set, not just 1 semaphore

int semop(int semid, struct sembuf *sops, unsigned int nsops);


/* changes the semaphore values, can work as P() and V()
operations based on arguments */

This value controls what


struct sembuf { happens. Positive means
ushort sem_num; V(), or releasing,
short sem_op; Negative means P() or
short sem_flg; acquiring
};

This will remove the


semctl(semid, 0, IPC_RMID) semaphore
Semaphore Example
class Semaphore{
private:
int semid;
public:
Semaphore (int value, int seed) Why do we need this??
{
key_t key = ftok ("a.txt", seed);
semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);
struct sembuf sb = {0,value,0};
semop(semid, &sb, 1); Sets initial = 0 + value
}
void P(){
struct sembuf sb = {0, -1, 0}; Notice we are trying to
semop(semid, &sb, 1): decrement. Works like a
} conditional wait until
void V(){
struct sembuf sb = {0, 1, 0}; value is at least 1
semop(semid, &sb, 1);
} This simply increments,
no wait here
};
Semaphore Demo
POSIX IPC: Overview
primitive POSIX function description
message queues msgget create or access
msgctl
control
msgsnd/msgrcv
send/receive message
semaphores semget create or access
semctl
control
semop
wait or post operation
shared memory shmget create and init or access
shmctl
control
shmat/shmdt
attach to / detach from
process

Accessing IPC resources from the shell: ipcs [-a]

You might also like