Professional Documents
Culture Documents
Software Component Design: Chapter 4: IPC Using Shared Memory, Pipes and Sockets
Software Component Design: Chapter 4: IPC Using Shared Memory, Pipes and Sockets
A shared memory segment is described by a control structure with a unique ID that points to
an area of physical memory. The identifier of the segment is called the shmid. The structure
definition for the shared memory segment control structures and prototypes can be found
in <sys/shm.h>.
Examples
We will write two programs for IPC using shared memory as an example. Program 1 will
create the shared segment, attach it, and then write some content in it. Then Program 2 will
attach itself to the shared segment and read the value written by Program 1.
Program 1: This program creates a shared memory segment, attaches itself to it, and then
writes some content into the shared memory segment.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>
int main()
{
int i;
void *shared_memory;
char buff[100];
int shmid;
shmid=shmget((key_t)2345, 1024, 0666|IPC_CREAT);
//creates shared memory segment with key 2345, having size 1024 bytes. IPC_CREAT is u
sed to create the shared segment if it does not exist. 0666 are the permissions on the sh
ared segment
printf("Key of shared memory is %d\n",shmid);
shared_memory=shmat(shmid,NULL,0);
//process attached to shared memory segment
printf("Process attached at %p\n",shared_memory);
//this prints the address where the segment is attached with this process
printf("Enter some data to write to shared memory\n");
read(0,buff,100); //get some input from user
strcpy(shared_memory,buff); //data written to shared memory
printf("You wrote : %s\n",(char *)shared_memory);
}
OUTPUT:
In the above program, the shmget() function creates a segment with key 2345, size
1024 bytes, and reads and writes permissions for all users. It returns the identifier of
the segment, which gets stored in shmid. This identifier is used in shmat() to attach
the shared segment to the process's address space.
NULL in shmat() means that the OS will itself attach the shared segment at a suitable
address of this process. Then some data is read from the user using
the read() system call, and it is finally written to the shared segment using
the strcpy() function.
Program 2: This program attaches itself to the shared memory segment created in
Program 1, and it reads the content of the shared memory.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>
int main()
{
int i;
void *shared_memory;
char buff[100];
int shmid;
shmid=shmget((key_t)2345, 1024, 0666);
printf("Key of shared memory is %d\n",shmid);
shared_memory=shmat(shmid,NULL,0); //process attached to shared memory segment
printf("Process attached at %p\n",shared_memory);
printf("Data read from shared memory is : %s\n",(char *)shared_memory);
}
OUTPUT
In this program, shmget() here generates the identifier of the same segment as
created in Program 1. Remember to give the same key value. The only change is, do
not write IPC_CREAT as the shared memory segment is already created.
Next, shmat() attaches the shared segment to the current process.
After that, the data is printed from the shared segment. In the output, you will see
the same data that you have written while executing Program 1.
Algorithm
Step 1 − Create a pipe.
Step 2 − Send a message to the pipe.
Step 3 − Retrieve the message from the pipe and write it to the standard output.
Step 4 − Send another message to the pipe.
Step 5 − Retrieve the message from the pipe and write it to the standard output.
Note − Retrieving messages can also be done after sending all messages.
Source Code: simplepipe.c
#include<stdio.h>
#include<unistd.h>
int main() {
int pipefds[2];
int returnstatus;
char writemessages[2][20]={"Hi", "Hello"};
char readmessage[20];
returnstatus = pipe(pipefds);
if (returnstatus == -1) {
printf("Unable to create pipe\n");
return 1;
}
Note − Ideally, return status needs to be checked for every system call. To simplify the
process, checks are not done for all the calls.
Execution Steps
Compilation
gcc -o simplepipe simplepipe.c
Execution/Output
Writing to pipe - Message 1 is Hi
Reading from pipe – Message 1 is Hi
Writing to pipe - Message 2 is Hi
Reading from pipe – Message 2 is Hell
Example program 2 − Program to write and read two messages through the pipe
using the parent and the child processes.
Algorithm
Step 1 − Create a pipe.
Step 2 − Create a child process.
Step 3 − Parent process writes to the pipe.
Step 4 − Child process retrieves the message from the pipe and writes it to the
standard output.
Step 5 − Repeat step 3 and step 4 once again.
Source Code: pipewithprocesses.c
#include<stdio.h>
#include<unistd.h>
int main() {
int pipefds[2];
int returnstatus;
int pid;
char writemessages[2][20]={"Hi", "Hello"};
char readmessage[20];
returnstatus = pipe(pipefds);
if (returnstatus == -1) {
printf("Unable to create pipe\n");
return 1;
}
pid = fork();
// Child process
if (pid == 0) {
read(pipefds[0], readmessage, sizeof(readmessage));
printf("Child Process - Reading from pipe – Message 1 is
%s\n", readmessage);
read(pipefds[0], readmessage, sizeof(readmessage));
printf("Child Process - Reading from pipe – Message 2 is
%s\n", readmessage);
} else { //Parent process
printf("Parent Process - Writing to pipe - Message 1 is
%s\n", writemessages[0]);
write(pipefds[1], writemessages[0],
sizeof(writemessages[0]));
printf("Parent Process - Writing to pipe - Message 2 is
%s\n", writemessages[1]);
write(pipefds[1], writemessages[1],
sizeof(writemessages[1]));
}
return 0;
}
Execution Steps
Compilation
gcc pipewithprocesses.c –o pipewithprocesses
Execution
Parent Process - Writing to pipe - Message 1 is Hi
Parent Process - Writing to pipe - Message 2 is Hello
Child Process - Reading from pipe – Message 1 is Hi
Child Process - Reading from pipe – Message 2 is Hello
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)
Stream Closing
The socket is discarded or closed by calling close().