Inter-Process Communication - Pipes

 Two processes often need to talk to each other. Most common example is client and server in network application. The client process asks for some information and server must supply that information. Since Unix (and Linux) is works in protected mode, one process can not directly access the data of another process. Hence there is a need for IPC. 

    The common tools used for IPC are
 
  a) Pipes and fifos
     b) System V IPCs - Message queues, Shared Memory and semaphore
    c) Signals
    d) Sockets
     e) Files

   Each of these is having its own pros and cons. Pipes and fifos can be used for communication of two processes running simultaneosly where pipe can work only if these processes are related. Message queues are used for sending and receiving messages which are destroyed after receiving. Shared memory is part of memory which is shared between two processes both of which can read and write to it with the drawback that it does not have any synchronization. Semaphore is used for synchronization of processes. Signals are asynchronous events which can be sent to a processes which can handle these signals. Sockets are used for communication of processes which are on local or remote systems. Files can be used also for IPC.

 

Pipes

Pipes are entities where data sent to one end of the pipe is available at the other end. In the kernel, pipe will have a buffer to store the data. Pipe has two descriptors like file descriptors. fd[0] is the read end of the pipe and fd[1] is write end of the pipe. To create a pipe in your program, you should use pipe(fd) system call where fd is array of two integers. int fd[2]; if (pipe(fd)< 0){ perror("Pipe creation error"); exit(1); } If the pipe can not be created, the pipe system call returns -1 . To wrie any data to the pipe, you can use write system call as follows. if (write(fd[1],"Hello world",6) < 0) perror("Write error to the pipe"); Now to read the data from the pipe. We can use read system call if ( (n=read(fd[0],str,20))<0) perror("read error"); else { str[n]='\0'; printf("Read from the pipe %s \n",str); } Of course the string read from the pipe will be "Hello world". But we are not doing anything useful by doing this. We need to have two processes, one which writes to the pipe and another which reads from the pipe. FOr that we should use fork after creating a pipe. #include<stdio.h> #include<sys/types.h> #include<unistd.h> int main() { int fd[2]; pid_t p1; if (pipe(fd)<0) { perror("pipe creation eror"); exit(1); } p1 = fork(); if(p1<0) { perror("fork error"); exit(1); } else if (p1) { /*The parent writes to the pipe*/ close(fd[0]); if(write(fd[1],"Hello from parent",17)<0) { perror("write to pipe error"); exit(1); } } else { /*The child reads from the pipe*/ char str[20]; int n; close(fd[1]); if( (n=read(fd[0],str,20))<0) { perror("write to pipe error"); exit(1); } else { str[n]='\0'; printf("Message read from the pipe is %s\n",str); } } } Note: 1) We add a null character ('\0') to the string because in low level read, this is not automatically done. 2) perror will print our message along with some description about the error So above program will let inter process communication between parent and child using the pipe.

Comments

Popular Posts