0% found this document useful (0 votes)
9 views20 pages

Unit-II LP

Shared memory allows communication between multiple processes by sharing a memory segment. Key system calls for managing shared memory include shmget() for creating segments, shmat() for attaching them, shmdt() for detaching, and shmctl() for control operations. The document also provides sample code for writing to and reading from shared memory using two separate processes.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views20 pages

Unit-II LP

Shared memory allows communication between multiple processes by sharing a memory segment. Key system calls for managing shared memory include shmget() for creating segments, shmat() for attaching them, shmdt() for detaching, and shmctl() for control operations. The document also provides sample code for writing to and reading from shared memory using two separate processes.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 20

Shared Memory

Shared memory is a memory shared between two or more processes. However,


why do we need to share memory or some other means of communication?

To reiterate, each process has its own address space, if any process wants to
communicate with some information from its own address space to other
processes, then it is only possible with IPC (inter process communication)
techniques. As we are already aware, communication can be between related or
unrelated processes.

Usually, inter-related process communication is performed using Pipes or Named


Pipes. Unrelated processes (say one process running in one terminal and another
process in another terminal) communication can be performed using Named Pipes
or through popular IPC techniques of Shared Memory and Message Queues.

We have seen the IPC techniques of Pipes and Named pipes and now it is time to
know the remaining IPC techniques viz., Shared Memory, Message Queues,
Semaphores, Signals, and Memory Mapping.

In this chapter, we will know all about shared memory.

We know that to communicate between two or more processes, we use shared


memory but before using the shared memory what needs to be done with the
system calls, let us see this −
 Create the shared memory segment or use an already created shared
memory segment (shmget())
 Attach the process to the already created shared memory segment (shmat())
 Detach the process from the already attached shared memory segment
(shmdt())
 Control operations on the shared memory segment (shmctl())

Let us look at a few details of the system calls related to shared memory.
shmget() system call:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg)
The above system call creates or allocates a System V shared memory segment.
The arguments that need to be passed are as follows −
The first argument, key, recognizes the shared memory segment. The key can
be either an arbitrary value or one that can be derived from the library function
ftok(). The key can also be IPC_PRIVATE, means, running processes as server and
client (parent and child relationship) i.e., inter-related process communiation. If the
client wants to use shared memory with this key, then it must be a child process of
the server. Also, the child process needs to be created after the parent has
obtained a shared memory.
The second argument, size, is the size of the shared memory segment rounded
to multiple of PAGE_SIZE.
The third argument, shmflg, specifies the required shared memory flag/s such
as IPC_CREAT (creating new segment) or IPC_EXCL (Used with IPC_CREAT to create
new segment and the call fails, if the segment already exists). Need to pass the
permissions as well.
Note − Refer earlier sections for details on permissions.
This call would return a valid shared memory identifier (used for further calls of
shared memory) on success and -1 in case of failure. To know the cause of failure,
check with errno variable or perror() function.
shmat() system call:
#include <sys/types.h>
#include <sys/shm.h>
void * shmat(int shmid, const void *shmaddr, int shmflg)
The above system call performs shared memory operation for System V shared
memory segment i.e., attaching a shared memory segment to the address space of
the calling process. The arguments that need to be passed are as follows −
The first argument, shmid, is the identifier of the shared memory segment. This
id is the shared memory identifier, which is the return value of shmget() system
call.
The second argument, shmaddr, is to specify the attaching address. If shmaddr
is NULL, the system by default chooses the suitable address to attach the segment.
If shmaddr is not NULL and SHM_RND is specified in shmflg, the attach is equal to
the address of the nearest multiple of SHMLBA (Lower Boundary Address).
Otherwise, shmaddr must be a page aligned address at which the shared memory
attachment occurs/starts.
The third argument, shmflg, specifies the required shared memory flag/s such
as SHM_RND (rounding off address to SHMLBA) or SHM_EXEC (allows the contents
of segment to be executed) or SHM_RDONLY (attaches the segment for read-only
purpose, by default it is read-write) or SHM_REMAP (replaces the existing mapping
in the range specified by shmaddr and continuing till the end of segment).
This call would return the address of attached shared memory segment on success
and -1 in case of failure. To know the cause of failure, check with errno variable or
perror() function.

shmdt() system call:


#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr)
The above system call performs shared memory operation for System V shared
memory segment of detaching the shared memory segment from the address
space of the calling process. The argument that needs to be passed is −
The argument, shmaddr, is the address of shared memory segment to be
detached. The to-be-detached segment must be the address returned by the
shmat() system call.
This call would return 0 on success and -1 in case of failure. To know the cause of
failure, check with errno variable or perror() function.
shmctl() system call:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
The above system call performs control operation for a System V shared memory
segment. The following arguments needs to be passed −
The first argument, shmid, is the identifier of the shared memory segment. This id
is the shared memory identifier, which is the return value of shmget() system call.
The second argument, cmd, is the command to perform the required control
operation on the shared memory segment.
Valid values for cmd are −
 IPC_STAT − Copies the information of the current values of each member of
struct shmid_ds to the passed structure pointed by buf. This command
requires read permission to the shared memory segment.
 IPC_SET − Sets the user ID, group ID of the owner, permissions, etc. pointed
to by structure buf.
 IPC_RMID − Marks the segment to be destroyed. The segment is destroyed
only after the last process has detached it.
 IPC_INFO − Returns the information about the shared memory limits and
parameters in the structure pointed by buf.
 SHM_INFO − Returns a shm_info structure containing information about the
consumed system resources by the shared memory.
The third argument, buf, is a pointer to the shared memory structure named struct
shmid_ds. The values of this structure would be used for either set or get as per
cmd.
This call returns the value depending upon the passed command. Upon success of
IPC_INFO and SHM_INFO or SHM_STAT returns the index or identifier of the shared
memory segment or 0 for other operations and -1 in case of failure. To know the
cause of failure, check with errno variable or perror() function.
APIs for Shared Memory
In Linux, shared memory can be implemented using several APIs that allow
processes to map a segment of memory into their address space to facilitate fast,
large-scale data sharing. Here are some common APIs for shared memory in Linux:

Key
API Description Advantages Use Cases
Functions/Calls
Uses POSIX API Simple,
for creating portable
POSIX Shared shared memory Portable, shared
shm_open, mmap,
Memory objects flexible size memory,
shm_unlink
(shm_open) accessible by allocation frequently
multiple used in UNIX-
processes like systems
Uses System V
Backward
IPC API for Legacy
compatibility,
System V Shared creating and shmget, shmat, systems,
better control
Memory (shmget) managing shmdt, shmctl backward
of
shared memory compatibility
permissions
segments
Maps a file or
device into Shared
File-backed,
memory, access to
Memory-Mapped mmap, munmap, persistent,
allowing shared large files,
Files (mmap) msync flexible
access by inter-process
mapping
multiple data sharing
processes
Uses mmap
Direct
without file Temporary
Anonymous
backing, Simplifies data sharing
Mapping (mmap mmap with
creating an allocation (no between
with MAP_ANONYMOUS
anonymous file needed) processes,
MAP_ANONYMOU
memory faster setup
S)
mapping
Semaphores Used
often used with sem_open, alongside
POSIX Synchronizes
shared memory sem_wait, shared
Semaphores (for access
for sem_post, memory for
sync) effectively
synchronization sem_close data
of access consistency

Let us consider the following sample program.


 Create two processes, one is for writing into the shared memory
(shm_write.c) and another is for reading from the shared memory
(shm_read.c)
 The program performs writing into the shared memory by write process
(shm_write.c) and reading from the shared memory by reading process
(shm_read.c)
 In the shared memory, the writing process, creates a shared memory of size
1K (and flags) and attaches the shared memory
 The write process writes 5 times the Alphabets from ‘A’ to ‘E’ each of 1023
bytes into the shared memory. Last byte signifies the end of buffer
 Read process would read from the shared memory and write to the standard
output
 Reading and writing process actions are performed simultaneously
 After completion of writing, the write process updates to indicate completion
of writing into the shared memory (with complete variable in struct shmseg)
 Reading process performs reading from the shared memory and displays on
the output until it gets indication of write process completion (complete
variable in struct shmseg)
 Performs reading and writing process for a few times for simplication and
also in order to avoid infinite loops and complicating the program

Following is the code for write process (Writing into Shared Memory – File:
shm_write.c)
/* Filename: shm_write.c */
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>

#define BUF_SIZE 1024


#define SHM_KEY 0x1234

struct shmseg {
int cnt;
int complete;
char buf[BUF_SIZE];
};
int fill_buffer(char * bufptr, int size);

int main(int argc, char *argv[]) {


int shmid, numtimes;
struct shmseg *shmp;
char *bufptr;
int spaceavailable;
shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
return 1;
}

// Attach to the segment to get a pointer to it.


shmp = shmat(shmid, NULL, 0);
if (shmp == (void *) -1) {
perror("Shared memory attach");
return 1;
}

/* Transfer blocks of data from buffer to shared memory */


bufptr = shmp->buf;
spaceavailable = BUF_SIZE;
for (numtimes = 0; numtimes < 5; numtimes++) {
shmp->cnt = fill_buffer(bufptr, spaceavailable);
shmp->complete = 0;
printf("Writing Process: Shared Memory Write: Wrote %d bytes\n", shmp->cnt);
bufptr = shmp->buf;
spaceavailable = BUF_SIZE;
sleep(3);
}
printf("Writing Process: Wrote %d times\n", numtimes);
shmp->complete = 1;

if (shmdt(shmp) == -1) {
perror("shmdt");
return 1;
}

if (shmctl(shmid, IPC_RMID, 0) == -1) {


perror("shmctl");
return 1;
}
printf("Writing Process: Complete\n");
return 0;
}

int fill_buffer(char * bufptr, int size) {


static char ch = 'A';
int filled_count;

//printf("size is %d\n", size);


memset(bufptr, ch, size - 1);
bufptr[size-1] = '\0';
if (ch > 122)
ch = 65;
if ( (ch >= 65) && (ch <= 122) ) {
if ( (ch >= 91) && (ch <= 96) ) {
ch = 65;
}
}
filled_count = strlen(bufptr);

//printf("buffer count is: %d\n", filled_count);


//printf("buffer filled is:%s\n", bufptr);
ch++;
return filled_count;
}
Compilation and Execution Steps
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Wrote 5 times
Writing Process: Complete

Following is the code for read process (Reading from the Shared Memory and
writing to the standard output – File: shm_read.c)
/* Filename: shm_read.c */
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>

#define BUF_SIZE 1024


#define SHM_KEY 0x1234

struct shmseg {
int cnt;
int complete;
char buf[BUF_SIZE];
};

int main(int argc, char *argv[]) {


int shmid;
struct shmseg *shmp;
shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
return 1;
}

// Attach to the segment to get a pointer to it.


shmp = shmat(shmid, NULL, 0);
if (shmp == (void *) -1) {
perror("Shared memory attach");
return 1;
}

/* Transfer blocks of data from shared memory to stdout*/


while (shmp->complete != 1) {
printf("segment contains : \n\"%s\"\n", shmp->buf);
if (shmp->cnt == -1) {
perror("read");
return 1;
}
printf("Reading Process: Shared Memory: Read %d bytes\n", shmp->cnt);
sleep(3);
}
printf("Reading Process: Reading Done, Detaching Shared Memory\n");
if (shmdt(shmp) == -1) {
perror("shmdt");
return 1;
}
printf("Reading Process: Complete\n");
return 0;
}
Compilation and Execution Steps
segment contains :
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAA"
Reading Process: Shared Memory: Read 1023 bytes
segment contains :
"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
Reading Process: Shared Memory: Read 1023 bytes
segment contains :
"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
Reading Process: Shared Memory: Read 1023 bytes
segment contains :
"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
Reading Process: Shared Memory: Read 1023 bytes
segment contains :
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
Reading Process: Shared Memory: Read 1023 bytes
Reading Process: Reading Done, Detaching Shared Memory
Reading Process: Complete
Inter-process Communication with Sockets
Inter-process communication is the mechanism provided by the operating system
that allows processes to communicate with each other. This communication could
involve a process letting another process know that some event has occurred or
transferring of data from one process to another.
One of the ways to manage interprocess communication is by using sockets. They
provide point-to-point, two-way communication between two processes. Sockets are
an endpoint of communication and a name can be bound to them. A socket can be
associated with one or more processes.
Types of Sockets
The different types of sockets are given as follows −
 Sequential Packet Socket: This type of socket provides a reliable
connection for datagrams whose maximum length is fixed This connection is
two-way as well as sequenced.
 Datagram Socket: A two-way flow of messages is supported by the
datagram socket. The receiver in a datagram socket may receive messages
in a different order than that in which they were sent. The operation of
datagram sockets is similar to that of passing letters from the source to the
destination through a mail.
 Stream Socket: Stream sockets operate like a telephone conversation and
provide a two-way and reliable flow of data with no record boundaries. This
data flow is also sequenced and unduplicated.
 Raw Socket: The underlying communication protocols can be accessed
using the raw sockets.
Socket Creation
Sockets can be created in a specific domain and the specific type using the
following declaration −
int socket(int domain, int type, int protocol)
If the protocol is not specified in the above system call, the system uses a default
protocol that supports the socket type. The socket handle is returned. It is a
descriptor.

The bind function call is used to bind an internet address or path to a socket. This is
shown as follows −
int bind(int s, const struct sockaddr *name, int namelen)
Connecting Stream Sockets
Connecting the stream sockets is not a symmetric process. One of the processes
acts as a server and the other acts as a client. The server specifies the number of
connection requests that can be queued using the following declaration −
int listen(int s, int backlog)

The client initiates a connection to the server’s socket by using the following
declaration −
int connect(int s, struct sockaddr *name, int namelen)
A new socket descriptor which is valid for that particular connection is returned by
the following declaration −
int accept(int s, struct sockaddr *addr, int *addrlen)
Stream Data Transfer
The send() and recv() functions are used to send and receive data using sockets.
These are similar to the read() and write() functions but contain some extra flags.
The declaration for send() and recv() are as follows −
int send(int s, const char *msg, int len, int flags)
int recv(int s, char *buf, int len, int flags)
Stream Closing
The socket is discarded or closed by calling close().
Closing: Both client and server should close the socket after communication using
the close() function.
close(server_fd);

IPC:Sockets
Sockets provide point-to-point, two-way communication between two processes.
Sockets are very versatile and are a basic component of interprocess and
intersystem communication. A socket is an endpoint of communication to which a
name can be bound. It has a type and one or more associated processes.
Sockets exist in communication domains. A socket domain is an abstraction that
provides an addressing structure and a set of protocols. Sockets connect only with
sockets in the same domain. Twenty three socket domains are identified (see
<sys/socket.h>), of which only the UNIX and Internet domains are normally used
Solaris 2.x Sockets can be used to communicate between processes on a single
system, like other forms of IPC.
The UNIX domain provides a socket address space on a single system. UNIX domain
sockets are named with UNIX paths. Sockets can also be used to communicate
between processes on different systems. The socket address space between
connected systems is called the Internet domain.
Internet domain communication uses the TCP/IP internet protocol suite.
Socket types define the communication properties visible to the application.
Processes communicate only between sockets of the same type. There are five
types of socket.
A stream socket
-- provides two-way, sequenced, reliable, and unduplicated flow of data with
no record boundaries. A stream operates much like a telephone conversation.
The socket type is SOCK_STREAM, which, in the Internet domain, uses
Transmission Control Protocol (TCP).
A datagram socket
-- supports a two-way flow of messages. A on a datagram socket may receive
messages in a different order from the sequence in which the messages were
sent. Record boundaries in the data are preserved. Datagram sockets
operate much like passing letters back and forth in the mail. The socket type
is SOCK_DGRAM, which, in the Internet domain, uses User Datagram Protocol
(UDP).
A sequential packet socket
-- provides a two-way, sequenced, reliable, connection, for datagrams of a
fixed maximum length. The socket type is SOCK_SEQPACKET. No protocol for
this type has been implemented for any protocol family.
A raw socket
provides access to the underlying communication protocols.
These sockets are usually datagram oriented, but their exact characteristics depend
on the interface provided by the protocol.
Socket Creation and Naming
int socket(int domain, int type, int protocol) is called to create a socket in the
specified domain and of the specified type. If a protocol is not specified, the system
defaults to a protocol that supports the specified socket type. The socket handle (a
descriptor) is returned. A remote process has no way to identify a socket until an
address is bound to it. Communicating processes connect through addresses. In the
UNIX domain, a connection is usually composed of one or two path names. In the
Internet domain, a connection is composed of local and remote addresses and local
and remote ports. In most domains, connections must be unique.
int bind(int s, const struct sockaddr *name, int namelen) is called to bind a path or
internet address to a socket. There are three different ways to call bind(),
depending on the domain of the socket.
 For UNIX domain sockets with paths containing 14, or fewer characters, you
can:
 #include <sys/socket.h>
 ...
 bind (sd, (struct sockaddr *) &addr, length);
 If the path of a UNIX domain socket requires more characters, use:
 #include <sys/un.h>
 ...
 bind (sd, (struct sockaddr_un *) &addr, length);
 For Internet domain sockets, use
 #include <netinet/in.h>
 ...
 bind (sd, (struct sockaddr_in *) &addr, length);
In the UNIX domain, binding a name creates a named socket in the file system.
Use unlink() or rm () to remove the socket.
Connecting Stream Sockets
Connecting sockets is usually not symmetric. One process usually acts as a server
and the other process is the client. The server binds its socket to a previously
agreed path or address. It then blocks on the socket. For a SOCK_STREAM socket,
the server calls int listen(int s, int backlog) , which specifies how many connection
requests can be queued. A client initiates a connection to the server's socket by a
call to int connect(int s, struct sockaddr *name, int namelen) . A UNIX domain call is
like this:
struct sockaddr_un server;
...
connect (sd, (struct sockaddr_un *)&server, length);
while an Internet domain call would be:
struct sockaddr_in;
...
connect (sd, (struct sockaddr_in *)&server, length);
If the client's socket is unbound at the time of the connect call, the system
automatically selects and binds a name to the socket. For a SOCK_STREAM socket,
the server calls accept(3N) to complete the connection.
int accept(int s, struct sockaddr *addr, int *addrlen) returns a new socket descriptor
which is valid only for the particular connection. A server can have
multiple SOCK_STREAM connections active at one time.
Stream Data Transfer and Closing
Several functions to send and receive data from a SOCK_STREAM socket. These
are write(), read(), int send(int s, const char *msg, int len, int flags), and int recv(int
s, char *buf, int len, int flags). send() and recv() are very similar
to read() and write(), but have some additional operational flags.
The flags parameter is formed from the bitwise OR of zero or more of the following:
MSG_OOB
-- Send "out-of-band" data on sockets that support this notion. The underlying
protocol must also support "out-of-band" data. Only SOCK_STREAM sockets
created in the AF_INET address family support out-of-band data.
MSG_DONTROUTE
-- The SO_DONTROUTE option is turned on for the duration of the operation. It
is used only by diagnostic or routing pro- grams.
MSG_PEEK
-- "Peek" at the data present on the socket; the data is returned, but not
consumed, so that a subsequent receive operation will see the same data.
A SOCK_STREAM socket is discarded by calling close().
Datagram sockets
A datagram socket does not require that a connection be established. Each
message carries the destination address. If a particular local address is needed, a
call to bind() must precede any data transfer. Data is sent through calls
to sendto() or sendmsg(). The sendto() call is like a send() call with the destination
address also specified. To receive datagram socket messages,
call recvfrom() or recvmsg(). While recv() requires one buffer for the arriving
data, recvfrom() requires two buffers, one for the incoming message and another to
receive the source address.
Datagram sockets can also use connect() to connect the socket to a specified
destination socket. When this is done, send() and recv() are used to send and
receive data.
accept() and listen() are not used with datagram sockets.
Socket Options
Sockets have a number of options that can be fetched with getsockopt() and set
with setsockopt(). These functions can be used at the native socket level (level =
SOL_SOCKET), in which case the socket option name must be specified. To
manipulate options at any other level the protocol number of the desired protocol
controlling the option of interest must be specified
(see getprotoent() in getprotobyname()).

Example Socket Programs:socket_server.c,socket_client


These two programs show how you can establish a socket connection using the
above functions.
socket_server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define NSTRS 3 /* no. of strings */


#define ADDRESS "mysocket" /* addr to connect */
/*
* Strings we send to the client.
*/
char *strs[NSTRS] = {
"This is the first string from the server.\n",
"This is the second string from the server.\n",
"This is the third string from the server.\n"
};

main()
{
char c;
FILE *fp;
int fromlen;
register int i, s, ns, len;
struct sockaddr_un saun, fsaun;

/*
* Get a socket to work with. This socket will
* be in the UNIX domain, and will be a
* stream socket.
*/
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
perror("server: socket");
exit(1);
}

/*
* Create the address we will be binding to.
*/
saun.sun_family = AF_UNIX;
strcpy(saun.sun_path, ADDRESS);

/*
* Try to bind the address to the socket. We
* unlink the name first so that the bind won't
* fail.
*
* The third argument indicates the "length" of
* the structure, not just the length of the
* socket name.
*/
unlink(ADDRESS);
len = sizeof(saun.sun_family) + strlen(saun.sun_path);

if (bind(s, &saun, len) < 0) {


perror("server: bind");
exit(1);
}
/*
* Listen on the socket.
*/
if (listen(s, 5) < 0) {
perror("server: listen");
exit(1);
}

/*
* Accept connections. When we accept one, ns
* will be connected to the client. fsaun will
* contain the address of the client.
*/
if ((ns = accept(s, &fsaun, &fromlen)) < 0) {
perror("server: accept");
exit(1);
}

/*
* We'll use stdio for reading the socket.
*/
fp = fdopen(ns, "r");

/*
* First we send some strings to the client.
*/
for (i = 0; i < NSTRS; i++)
send(ns, strs[i], strlen(strs[i]), 0);

/*
* Then we read some strings from the client and
* print them out.
*/
for (i = 0; i < NSTRS; i++) {
while ((c = fgetc(fp)) != EOF) {
putchar(c);

if (c == '\n')
break;
}
}

/*
* We can simply use close() to terminate the
* connection, since we're done with both sides.
*/
close(s);

exit(0);
}
socket_client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define NSTRS 3 /* no. of strings */


#define ADDRESS "mysocket" /* addr to connect */

/*
* Strings we send to the server.
*/
char *strs[NSTRS] = {
"This is the first string from the client.\n",
"This is the second string from the client.\n",
"This is the third string from the client.\n"
};

main()
{
char c;
FILE *fp;
register int i, s, len;
struct sockaddr_un saun;

/*
* Get a socket to work with. This socket will
* be in the UNIX domain, and will be a
* stream socket.
*/
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
perror("client: socket");
exit(1);
}

/*
* Create the address we will be connecting to.
*/
saun.sun_family = AF_UNIX;
strcpy(saun.sun_path, ADDRESS);

/*
* Try to connect to the address. For this to
* succeed, the server must already have bound
* this address, and must have issued a listen()
* request.
*
* The third argument indicates the "length" of
* the structure, not just the length of the
* socket name.
*/
len = sizeof(saun.sun_family) + strlen(saun.sun_path);

if (connect(s, &saun, len) < 0) {


perror("client: connect");
exit(1);
}

/*
* We'll use stdio for reading
* the socket.
*/
fp = fdopen(s, "r");

/*
* First we read some strings from the server
* and print them out.
*/
for (i = 0; i < NSTRS; i++) {
while ((c = fgetc(fp)) != EOF) {
putchar(c);

if (c == '\n')
break;
}
}

/*
* Now we send some strings to the server.
*/
for (i = 0; i < NSTRS; i++)
send(s, strs[i], strlen(strs[i]), 0);

/*
* We can simply use close() to terminate the
* connection, since we're done with both sides.
*/
close(s);

exit(0);
}

Comparison of common Inter-Process Communication (IPC) mechanisms:


IPC Data
Communicat Persiste
Mechani Description Speed Transfe Use Cases
ion Type nce
sm r
Pipes Unidirectional Fast Unidirectional Byte Only Simple data
IPC Data
Communicat Persiste
Mechani Description Speed Transfe Use Cases
ion Type nce
sm r
, connects transfer
during
related between
stream process
processes related
life
(parent-child) processes
Similar to
pipes but can Communicatio
Named Exists
communicate Moderat Byte n between
Pipes Unidirectional until
between e stream unrelated
(FIFOs) deleted
unrelated processes
processes
Allows Asynchronous
messages to Structure data
Exists
Message be queued for Moderat d exchange,
Bidirectional until
Queues asynchronous e to fast message priority-based
deleted
communicatio s message
n handling
Fastest IPC,
Large data
shares
Exists sharing, low-
Shared memory Large
Fastest Bidirectional until latency
Memory space blocks
deleted communicatio
between
n
processes
Synchronizati Resource
on Exists access
Semaph
mechanism to Fast N/A N/A until control,
ores
control access deleted synchronizatio
to resources n
Network-
Networked
based
Exists processes,
communicatio Moderat Byte
Sockets Bidirectional until remote
n (TCP/UDP) e stream
closed communicatio
for local or
n
remote
Asynchronous Only
Notifications,
notifications during
Signals Fast N/A N/A event
to interrupt a process
handling
process life
Fast file
Memory- Maps files to Exists access,
Bidirectional File-
Mapped memory for Fast until file shared data
(Indirect) based
Files faster I/O closed across
processes

Each IPC mechanism has distinct features and is chosen based on the needs for
data transfer speed, type, synchronization, and whether the processes are related
or independent.

You might also like