Menu

Operating Systems [ Lab Programs ]


Aim:

  Write C programs to illustrate the following IPC mechanisms
a) Pipes
b) FIFOs
c) Message Queues
d) Shared Memory.

Solution :

a) Pipes

DESCRIPTION:

Pipe is a communication medium between two or more related or interrelated processes. It can be either within one process or a communication between the child and the parent processes. Communication can also be multi-level such as communication between the parent, the child and the grand-child, etc. Communication is achieved by one process writing into the pipe and other reading from the pipe. To achieve the pipe system call, create two files, one to write into the file and another to read from the file.

PROGRAM: ( pipes.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;
 }
 printf("Writing to pipe - Message 1 is %s\n", writemessages[0]);
 write(pipefds[1], writemessages[0], sizeof(writemessages[0]));
 read(pipefds[0], readmessage, sizeof(readmessage));
 printf("Reading from pipe - Message 1 is %s\n", readmessage);
 printf("Writing to pipe - Message 2 is %s\n", writemessages[1]);
 write(pipefds[1], writemessages[1], sizeof(writemessages[0]));
 read(pipefds[0], readmessage, sizeof(readmessage));
 printf("Reading from pipe - Message 2 is %s\n", readmessage);
 return 0;
}


OUTPUT:

 
$ gcc pipes.c
$ ./a.out
Writing to pipe - Message 1 is Hi
Reading from pipe - Message 1 is Hi
Writing to pipe - Message 2 is Hello
Reading from pipe - Message 2 is Hello


b) FIFOs

DESCRIPTION:

Pipes were meant for communication between related processes. Can we use pipes for unrelated process communication, say, we want to execute client program from one terminal and the server program from another terminal? The answer is No. Then how can we achieve unrelated processes communication, the simple answer is Named Pipes. Even though this works for related processes, it gives no meaning to use the named pipes for related process communication.

PROGRAM:

Server: ( fifo_server.c )

 
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

#define FIFO_SERVER "fifo_server"
#define FIFO_CLIENT "fifo_client"

int main()
{
    int fifo_server, fifo_client;
    int choice;
    char *buf;

    // Create FIFOs
    mkfifo(FIFO_SERVER, 0666);
    mkfifo(FIFO_CLIENT, 0666);

    // Open server FIFO for reading
    fifo_server = open(FIFO_SERVER, O_RDONLY);
    if (fifo_server < 0) {
        printf("Error opening server FIFO\n");
        return 1;
    }

    // Read choice from client
    read(fifo_server, &choice, sizeof(int));

    // Open client FIFO for writing
    fifo_client = open(FIFO_CLIENT, O_WRONLY);
    if (fifo_client < 0) {
        printf("Error opening client FIFO\n");
        return 1;
    }

    switch (choice) {
        case 1:
            buf = "Linux";
            break;
        case 2:
            buf = "Fedora";
            break;
        case 3:
            buf = "2.6.32";
            break;
        default:
            buf = "Invalid Choice";
    }

    write(fifo_client, buf, 10);
    printf("Data sent to client\n");

    close(fifo_server);
    close(fifo_client);

    return 0;
}



Server: ( fifo_client.c )

 
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

#define FIFO_SERVER "fifo_server"
#define FIFO_CLIENT "fifo_client"

int main()
{
    int fifo_server, fifo_client;
    int choice;
    char buf[10];

    printf("Choose the request to be sent to server\n");
    printf("1. OS Name\n2. Distribution\n3. Kernel Version\n");
    scanf("%d", &choice);

    // Open server FIFO for writing
    fifo_server = open(FIFO_SERVER, O_WRONLY);
    if (fifo_server < 0) {
        printf("Error opening server FIFO\n");
        exit(1);
    }

    write(fifo_server, &choice, sizeof(int));

    // Open client FIFO for reading
    fifo_client = open(FIFO_CLIENT, O_RDONLY);
    if (fifo_client < 0) {
        printf("Error opening client FIFO\n");
        exit(1);
    }

    read(fifo_client, buf, 10);
    printf("\n*** Reply from server: %s ***\n", buf);

    close(fifo_server);
    close(fifo_client);

    return 0;
}



OUTPUT:

 
Server:
-------
$gcc fifo_server.c -o server
$ ./server
Data sent to client

$ ./server
Data sent to client

Client:
-------
$ gcc fifo_client.c -o client
$ ./client
Choose the request to be sent to server
1. OS Name
2. Distribution
3. Kernel Version
2

*** Reply from server: Fedora ***

$ ./client
Choose the request to be sent to server
1. OS Name
2. Distribution
3. Kernel Version
3

*** Reply from server: 2.6.32 ***


c) Message Queues

DESCRIPTION:

A message queue is a linked list of messages stored within the kernel and identified by a message queue identifier. A new queue is created or an existing queue opened by msgget().New messages are added to the end of a queue by msgsnd(). Every message has a positive long integer type field, a non-negative length, and the actual data bytes (corresponding to the length), all of which are specified to msgsnd() when the message is added to a queue. Messages are fetched from a queue by msgrcv(). We don’t have to fetch the messages in a first-in, first-out order. Instead, we can fetch messages based on their type field.

PROGRAM:

Sender: ( Sender.c )

 
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<stdlib.h>
#define SIZE 2000
void main()
{
int mfd,mfd2,mfd3;
struct
{
double mtype;
char mtext[2000];
}s1,s2,s3;
if((mfd=msgget(1000,IPC_CREAT|0666))==-1)
{
perror("msgget:");
exit(1);
}
s1.mtype=1;
sprintf(s1.mtext,"%s","Hi friends... My name is message1");
if(msgsnd(mfd,&s1,1000,0)==-1)
{
perror("msgsnd");
exit(1);
}
if((mfd2=msgget(1000,IPC_CREAT|0666))==-1)
{
perror("msgget:");
exit(1);
}
s2.mtype=1;
sprintf(s2.mtext,"%s","Hi friends... My name is message2");
if(msgsnd(mfd2,&s2,1000,0)==-1)
{
perror("msgsnd");
exit(1);
}
if((mfd3=msgget(1000,IPC_CREAT|0666))==-1)
{
perror("msgget:");
exit(1);
}
s3.mtype=1;
sprintf(s3.mtext,"%s","Hi friends... My name is message3");
if(msgsnd(mfd3,&s3,1000,0)==-1)
{
perror("msgsnd");
exit(1);
}
printf("Your message has been sent successfully...\n");
printf("Please visit another (receiver's) terminal...\n");
printf("Thank you.... For using LINUX\n");
}

Receiver: ( receiver.c )

 
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#define SIZE 40
void main()
{
int mfd,mfd2,mfd3;
struct
{
long mtype;
char mtext[6];
}s1,s2,s3;
if((mfd=msgget(1000,0))==-1)
{
perror("msgget");
exit(1);
}
if(msgrcv(mfd,&s1,SIZE,0,IPC_NOWAIT|MSG_NOERROR)==-1)
{
perror("msgrcv");
exit(1);
}
printf("Message from client is :%s\n",s1.mtext);
if((mfd2=msgget(1000,0))==-1)
{
perror("msgget");
exit(1);
}
if(msgrcv(mfd2,&s2,SIZE,0,IPC_NOWAIT|MSG_NOERROR)==-1)
{
perror("msgrcv");
exit(1);
}
printf("Message from client is :%s\n",s2.mtext);
if((mfd3=msgget(1000,0))==-1)
{
perror("msgget");
exit(1);
}
if(msgrcv(mfd3,&s3,SIZE,0,IPC_NOWAIT|MSG_NOERROR)==-1)
{
perror("msgrcv");
exit(1);
}
printf("Message from sender is :%s\n",s3.mtext);
}

OUTPUT:

 
SENDER:
--------
$ gcc Sender.c -o sender
$ ./sender
Your message has been sent successfully...
Please visit another (receiver's) terminal...
Thank you.... For using LINUX


RECEIVER:
---------
$ gcc Receiver.c -o receiver
$ ./receiver
Message from client is :Hi friends... My name is message1
Message from client is :Hi friends... My name is message2
Message from sender is :Hi friends... My name is message3
*** stack smashing detected ***: terminated
Aborted (core dumped)


d) Shared Memory

DESCRIPTION:

Inter Process Communication through shared memory is a concept where two or more process can access the common memory. And communication is done via this shared memory where changes made by one process can be viewed by another process. The problem with pipes, fifo and message queue is that for two process to exchange information. The information has to go through the kernel. - Server reads from the input file.
- The server writes this data in a message using either a pipe, fifo or message queue.
- The client reads the data from the IPC channel,again requiring the data to be copied from kernel’s IPC buffer to the client's buffer.
- Finally the data is copied from the client's buffer.

PROGRAM:

Writer: ( shwriter.c )

 
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
int main ( )
{
 int segment_id;
 char bogus;
 char* shared_memory;
 struct shmid_ds shmbuffer;
 int segment_size;
 const int shared_segment_size = 0x6400;
 /* Allocate a shared memory segment. */
 segment_id = shmget (IPC_PRIVATE, shared_segment_size, IPC_CREAT
| IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
 /* Attach the shared memory segment. */
 printf("Shared memory segment ID is %d\n", segment_id);
 shared_memory = (char*) shmat (segment_id, 0, 0);
 printf ("shared memory attached at address %p\n", shared_memory);
 /* Determine the segment's size. */
 /*
 shmctl (segment_id, IPC_STAT, &shmbuffer);
 segment_size = shmbuffer.shm_segsz;
 printf ("segment size: %d\n", segment_size);
 */
 /* Write a string to the shared memory segment. */
 sprintf (shared_memory, "Hello, world.");
 /* Detach the shared memory segment. */
 shmdt (shared_memory);
 printf("Wrote Hello World to the segment\n");
}

Reader: ( shreader.c )

 
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
int main ()
{
 int segment_id;
 char bogus;
 char* shared_memory;
 struct shmid_ds shmbuffer;
 int segment_size;
 const int shared_segment_size = 0x6400;
 printf("Enter the shared memory id: ");
 scanf("%d", &segment_id);
 /* Reattach the shared memory segment, at a different address. */
 shared_memory = (char*) shmat (segment_id, (void*) 0x5000000, 0);
 printf ("shared memory reattached at address %p\n", shared_memory);
 /* Print out the string from shared memory. */
 printf ("The contents of the shared memory is:\n%s\n",
shared_memory);
 /* Detach the shared memory segment. */
 shmdt (shared_memory);
 return 0;
}

OUTPUT:

 
Writer :
---------
$ gcc shwriter.c -o shwriter
$ ./shwriter
Shared memory segment ID is 3
shared memory attached at address 0x7525a2f27000
Wrote Hello World to the segment


Reader :
----------
$ gcc shreader.c -o shreader
$ ./shreader
Enter the shared memory id: 3
shared memory reattached at address 0x5000000
The contents of the shared memory is:
Hello, world.



Related Content :

1. Write C programs to simulate the following CPU Scheduling algorithms
a) FCFS
b) SJF
c) RoundRobin
d) priority    View Solution


2. Write programs using the I/O system calls of UNIX/LINUX operating system (open, read, write, close,fcntl, seek, stat, opendir, readdir)    View Solution


3. Write a C program to simulate Bankers Algorithm for Deadlock Avoidance and Prevention.    View Solution


4. Write a C program to implement the Producer – Consumer problem using semaphores using UNIX/LINUX system calls.   View Solution


5. Write C programs to illustrate the following IPC mechanisms
a) Pipes
b) FIFOs
c) Message Queues
d) Shared Memory.    View Solution


6. Write C programs to simulate the following memory management techniques
a) Paging
b) Segmentation    View Solution


7. Write C programs to simulate Page replacement policies
a) FCFS
b) LRU
c) Optimal    View Solution