Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
IPC - PIPE
UNIX SYSTEM
PROGRAMMING
Creating pipe
Pipe is a method of connecting standard output of
one process to the standard input of another.
Pipes provide one-way communication(half-
duplex).
Eg: ls | sort
The output of ls command (program) is passed as
input to sort command (program)
 When a process creates a pipe, the kernel sets up two
file descriptors for use by the pipe. One descriptor is
used to allow a path of input into the pipe (write),
while the other is used to obtain data from the pipe
(read).
Creating pipe
int pipe(int fd[2]);
We need to pass array of 2 integers to
pipe.
fd[0] will be filled with file descriptor for
reading.
fd[1] will be filled with file descriptor for
writing.
#include <unistd.h>
int main()
{
int fd [2] = {0,0};
pipe( fd);
printf(" %d ",fd[0]);
printf(" %d " , fd[1]);
}
Writing to and reading from pipe
Blocking Pipe
 If a process tries to read before something is written to the
pipe, the process is suspended until something is written.
main()
{
int pipefd [2] = {0,0};
pipe( pipefd);
char output[] = "hello worldn";
char input[20]= "SIKANDER";
read (pipefd[0], input, sizeof (input)) ;
write (pipefd[1], output, sizeof(output));
printf("Data Read from pipe = %s n" , input );
}
Broken Pipe
 Writing to a pipe where Read end is closed.
 Creating a pipe to communicate within the same
process is useless.
 Pipe are used to communicate between parent and
child process. Since a child process will inherit any
open file descriptors from the parent, we now have
the basis for multiprocess communication (between
parent and child).
Pipe
Child Writes and Parent Reads
if(fork() == 0)
{
printf("CHILD WRITES n");
write(fd[1], “SIKANDER” , 9);
}
else {
char input[20]= “";
if( ( n = read ( fd[0] , input, sizeof (input) ) ) > 0 )
printf("Parent read the data %s n" , input);
}
Parent Writes and Child Reads
if(fork() == 0) {
char input[20]= "";
if( ( n = read ( fd[0] , input, sizeof (input) ) ) > 0 )
printf("Child read the data : %s n" , input);
exit(0);
}
else{
write(fd[1], “SIKANDER” , 9);
}
 Generally, one process writes the data to pipe and
other process reads data from pipe.
 In which direction do we desire data to travel? Does
the child process send information to the parent, or
vice-versa?
 The two processes mutually agree on this issue, and
proceed to ``close'' the end of the pipe that they are
not concerned with. For discussion purposes, let's
say the child performs some processing, and sends
information back through the pipe to the parent.
Pipe
2-way communication
 Parent writes and child read
 Child writes and parent reads
Parent Child
Pipe p1
Pipe p2
0
1
2
P1- R 3 (X)
P1 - W 4
P2 – R 5
P2 – W 6 (X)
0
1
2
P1- R 3
P1 - W 4 (X)
P2 – R 5 (X)
P2 – W 6
#include <unistd.h>
int main()
{
int p1[2] = {0,0}, p2[2];
pipe(p1); pipe(p2);
if(fork() == 0)
{
printf("CHILD PROCESS n");
close(p1[0]); close(p2[1]);
char cbuf[20] = " ";
write(p1[1], "HAI FROM CHILD" , 20);
read(p2[0] , cbuf , 20);
printf("child read %s n",cbuf);
}
else
{
printf("PARENT PROCESS n");
close(p1[1]); close(p2[0]);
char buffer[20];
buffer[read(p1[0] , buffer , 20)] = '0';
printf("parent read : %s n",buffer);
write(p2[1] ,”PARENT n", 20);
}
}
Implement command
 ls | wc int fd [2] = {0,0}, n;
pipe( fd) ;
if(fork() == 0)
{
close(fd[0]);
dup2(fd[1] , 1);
execlp("ls","ls",0);
}
else
{
close(fd[1]);
dup2(fd[0] , 0);
execlp("wc","wc",0);
}
1. Create a pipe.
2. Create a child process
Inside Child Process
1. Close read end of pipe
2. Redirect the stdout to fd[1]
3. Execute ls cmd using execlp
Inside Parent Process
1. Close write end of pipe
2. Redirect the stdin to fd[0]
3. Execute wc cmd using execlp
Implement command - Incomplete
 ls | wc
Ls -
l Ls – l | head -4
0
1
2
3(x)
4(x)
5(dup – 0)
6(x)
0
1
2
3(dup – 0)
4(x)
5(x)
6(dup – 1)
First Child Second Child parent
Implement command
 ls | head -4 | tail -1
Ls -
l Ls – l | head -4
0
1
2
3 (x)
4(dup – 1)
0
1
2
3(x)
4(x)
5(dup – 0)
6(x)
0
1
2
3(dup – 0)
4(x)
5(x)
6(dup – 1)
First Child Second Child parent
main()
{
int fd [2] = {0,0}, n;
pipe( fd);
if(fork() == 0)
{ //First Child
close(fd[0]);
dup2(fd[1] , 1);
execlp("ls","ls","-l",0);
}
else
{
int fd1[2] = {0};
pipe(fd1) ;
if(fork() == 0)
{
//Second Child
//Second Child
close(fd[1]);
close(fd1[0]);
dup2(fd[0] , 0);
dup2(fd1[1] , 1);
execlp("head","head","-4",0);
}
else{
//Parent
close(fd[0]); close(fd[1]);
close(fd1[1]);
dup2(fd1[0] , 0);
execlp("tail","tail","-1",0);
}
}
}
Names Pipes
 Unnamed Pipes – Cannot use open system call.
 named Pipes – Can use open system call. (Can open but
cannot create a file).
 Unnamed and named has 2 file descriptors (read end and
write end).
 Write from one end and read from other end.
 Named pipes also called FIFO
 Destructive reading.
 Persistency is different (File system persistency).
 Can communicate between related and unrelated
process.
 File name will be stored permanently, data is temporary
 Half duplex comm
 Pipe size is 4kb
 Blocking effect and broken pipe.
named Pipe
 Creating Named Pipe from Command Prompt
 Mknod filename p
 Mkfifo filename
 $mkfifo PIPE
 prw-rw-r-- 1 sik sik 0 Sep 11 15:13 PIPE
 Size of named pipe is always 0.
 Type of file is p.
 Cannot open file in vi editor / cat.
“
 Creating Named Pipe using function calls.
 int mkfifo(const char *path, mode_t mode);
 mkfifo(“PIPE“ , 0666);
Named Pipe : Same Process
main()
{
mkfifo("mypipe“, 0666);
if(fork() == 0)
{
int fd = open("mypipe",O_WRONLY);
printf("Child : Write mode : %d n",fd);
write(fd,"HELLO",5);
}
else
{
char buff[6] = "";
int fd = open("mypipe",O_RDONLY);
printf("Parent : Read mode : %d n",fd);
buff[read(fd , buff , 5)] = '0';
printf("Message read = %s " , buff);
}
}
Pipe
Pipe
Pipe
 What is a pipe?
 How to create a unnamed pipe?
 What are the drawbacks of unnamed pipe?
 How to create a named pipe?
 Is the pipe created in parent, accessible in child process?
 If u create a child process, does the pipe get duplicated?

More Related Content

Pipe

  • 1. IPC - PIPE UNIX SYSTEM PROGRAMMING
  • 2. Creating pipe Pipe is a method of connecting standard output of one process to the standard input of another. Pipes provide one-way communication(half- duplex). Eg: ls | sort The output of ls command (program) is passed as input to sort command (program)
  • 3.  When a process creates a pipe, the kernel sets up two file descriptors for use by the pipe. One descriptor is used to allow a path of input into the pipe (write), while the other is used to obtain data from the pipe (read).
  • 4. Creating pipe int pipe(int fd[2]); We need to pass array of 2 integers to pipe. fd[0] will be filled with file descriptor for reading. fd[1] will be filled with file descriptor for writing. #include <unistd.h> int main() { int fd [2] = {0,0}; pipe( fd); printf(" %d ",fd[0]); printf(" %d " , fd[1]); }
  • 5. Writing to and reading from pipe
  • 6. Blocking Pipe  If a process tries to read before something is written to the pipe, the process is suspended until something is written. main() { int pipefd [2] = {0,0}; pipe( pipefd); char output[] = "hello worldn"; char input[20]= "SIKANDER"; read (pipefd[0], input, sizeof (input)) ; write (pipefd[1], output, sizeof(output)); printf("Data Read from pipe = %s n" , input ); }
  • 7. Broken Pipe  Writing to a pipe where Read end is closed.
  • 8.  Creating a pipe to communicate within the same process is useless.  Pipe are used to communicate between parent and child process. Since a child process will inherit any open file descriptors from the parent, we now have the basis for multiprocess communication (between parent and child).
  • 10. Child Writes and Parent Reads if(fork() == 0) { printf("CHILD WRITES n"); write(fd[1], “SIKANDER” , 9); } else { char input[20]= “"; if( ( n = read ( fd[0] , input, sizeof (input) ) ) > 0 ) printf("Parent read the data %s n" , input); } Parent Writes and Child Reads if(fork() == 0) { char input[20]= ""; if( ( n = read ( fd[0] , input, sizeof (input) ) ) > 0 ) printf("Child read the data : %s n" , input); exit(0); } else{ write(fd[1], “SIKANDER” , 9); }
  • 11.  Generally, one process writes the data to pipe and other process reads data from pipe.  In which direction do we desire data to travel? Does the child process send information to the parent, or vice-versa?  The two processes mutually agree on this issue, and proceed to ``close'' the end of the pipe that they are not concerned with. For discussion purposes, let's say the child performs some processing, and sends information back through the pipe to the parent.
  • 13. 2-way communication  Parent writes and child read  Child writes and parent reads Parent Child Pipe p1 Pipe p2 0 1 2 P1- R 3 (X) P1 - W 4 P2 – R 5 P2 – W 6 (X) 0 1 2 P1- R 3 P1 - W 4 (X) P2 – R 5 (X) P2 – W 6
  • 14. #include <unistd.h> int main() { int p1[2] = {0,0}, p2[2]; pipe(p1); pipe(p2); if(fork() == 0) { printf("CHILD PROCESS n"); close(p1[0]); close(p2[1]); char cbuf[20] = " "; write(p1[1], "HAI FROM CHILD" , 20); read(p2[0] , cbuf , 20); printf("child read %s n",cbuf); } else { printf("PARENT PROCESS n"); close(p1[1]); close(p2[0]); char buffer[20]; buffer[read(p1[0] , buffer , 20)] = '0'; printf("parent read : %s n",buffer); write(p2[1] ,”PARENT n", 20); } }
  • 15. Implement command  ls | wc int fd [2] = {0,0}, n; pipe( fd) ; if(fork() == 0) { close(fd[0]); dup2(fd[1] , 1); execlp("ls","ls",0); } else { close(fd[1]); dup2(fd[0] , 0); execlp("wc","wc",0); } 1. Create a pipe. 2. Create a child process Inside Child Process 1. Close read end of pipe 2. Redirect the stdout to fd[1] 3. Execute ls cmd using execlp Inside Parent Process 1. Close write end of pipe 2. Redirect the stdin to fd[0] 3. Execute wc cmd using execlp
  • 16. Implement command - Incomplete  ls | wc Ls - l Ls – l | head -4 0 1 2 3(x) 4(x) 5(dup – 0) 6(x) 0 1 2 3(dup – 0) 4(x) 5(x) 6(dup – 1) First Child Second Child parent
  • 17. Implement command  ls | head -4 | tail -1 Ls - l Ls – l | head -4 0 1 2 3 (x) 4(dup – 1) 0 1 2 3(x) 4(x) 5(dup – 0) 6(x) 0 1 2 3(dup – 0) 4(x) 5(x) 6(dup – 1) First Child Second Child parent
  • 18. main() { int fd [2] = {0,0}, n; pipe( fd); if(fork() == 0) { //First Child close(fd[0]); dup2(fd[1] , 1); execlp("ls","ls","-l",0); } else { int fd1[2] = {0}; pipe(fd1) ; if(fork() == 0) { //Second Child //Second Child close(fd[1]); close(fd1[0]); dup2(fd[0] , 0); dup2(fd1[1] , 1); execlp("head","head","-4",0); } else{ //Parent close(fd[0]); close(fd[1]); close(fd1[1]); dup2(fd1[0] , 0); execlp("tail","tail","-1",0); } } }
  • 19. Names Pipes  Unnamed Pipes – Cannot use open system call.  named Pipes – Can use open system call. (Can open but cannot create a file).  Unnamed and named has 2 file descriptors (read end and write end).  Write from one end and read from other end.  Named pipes also called FIFO  Destructive reading.  Persistency is different (File system persistency).  Can communicate between related and unrelated process.  File name will be stored permanently, data is temporary
  • 20.  Half duplex comm  Pipe size is 4kb  Blocking effect and broken pipe.
  • 21. named Pipe  Creating Named Pipe from Command Prompt  Mknod filename p  Mkfifo filename  $mkfifo PIPE  prw-rw-r-- 1 sik sik 0 Sep 11 15:13 PIPE  Size of named pipe is always 0.  Type of file is p.  Cannot open file in vi editor / cat.
  • 22. “  Creating Named Pipe using function calls.  int mkfifo(const char *path, mode_t mode);  mkfifo(“PIPE“ , 0666);
  • 23. Named Pipe : Same Process main() { mkfifo("mypipe“, 0666); if(fork() == 0) { int fd = open("mypipe",O_WRONLY); printf("Child : Write mode : %d n",fd); write(fd,"HELLO",5); } else { char buff[6] = ""; int fd = open("mypipe",O_RDONLY); printf("Parent : Read mode : %d n",fd); buff[read(fd , buff , 5)] = '0'; printf("Message read = %s " , buff); } }
  • 27.  What is a pipe?  How to create a unnamed pipe?  What are the drawbacks of unnamed pipe?  How to create a named pipe?  Is the pipe created in parent, accessible in child process?  If u create a child process, does the pipe get duplicated?

Editor's Notes

  1. Pipe1.c Output : 3 , 4 main() { int pipefd [2] = {0,0}; #ifdef OPEN open(__FILE__ , O_RDONLY); #endif pipe(pipefd); printf(" %d %d \n",pipefd[0] , pipefd[1]); }
  2. Pipe2.c At this point, the pipe is of little practical use, as the creating process can only use the pipe to communicate with itself. main() { int pipefd [2] = {0,0}, n; if( pipe( pipefd) == -1) { printf("can not create pipe \n"); return 1; } char output[] = "hello world\n"; char input[20]= "SIKANDER"; if (write (pipefd[1],output, sizeof(output))!= sizeof(output)) { printf("pipe write error \n"); } if( ( n = read ( pipefd[0] , input, sizeof (input) ) ) <= 0 ) { printf("pipe read error \n"); } puts(input); }
  3. Blocking Pipe #include <stdio.h> #include <stdlib.h> #include <unistd.h> main() { int pipefd [2] = {0,0}, n; //Creating a pipe pipe( pipefd); char output[] = "hello world\n"; char input[20]= "SIKANDER"; read (pipefd[0], input, sizeof (input)) ; write (pipefd[1], output, sizeof(output)); printf("Data Read from pipe = %s \n" , input ); }
  4. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> void myhandler(int signo) { printf("SIGNAL HANDLER \n"); printf("Signal number = %d \n" , signo); } main() { int pipefd [2] = {0,0}, n; if( pipe( pipefd) == -1) { printf("can not create pipe \n"); return 1; } signal(SIGPIPE , myhandler); #ifdef CLOSEREAD close(pipefd[0]); #endif if(write (pipefd[1],"hello world\n", 12)!= 12) { printf("pipe write error \n"); } }
  5. At this point, the pipe is fairly useless. After all, why go to the trouble of creating a pipe if we are only going to talk to ourself? At this point, the creating process typically forks a child process. Since a child process will inherit any open file descriptors from the parent, we now have the basis for multiprocess communication (between parent and child).
  6. Pipechildparent.c #include <stdio.h> #include <unistd.h> int main() { int fd[2]; pipe(fd); if(fork() == 0) { printf("CHILD WRITES \n"); sleep(2); write(fd[1], "SIKANDER" , 9); printf("Child Writing done \n"); } else { char input[20]= ""; printf("Parent Process Started \n"); if( read ( fd[0] , input, sizeof (input) ) > 0 ) printf("Parent read the data %s \n" , input); } }
  7. Above, we see that both processes now have access to the file descriptors which constitute the pipeline. It is at this stage, that a critical decision must be made. In which direction do we desire data to travel? Does the child process send information to the parent, or vice-versa? The two processes mutually agree on this issue, and proceed to ``close'' the end of the pipe that they are not concerned with. For discussion purposes, let's say the child performs some processing, and sends information back through the pipe to the parent. Construction of the pipeline is now complete! The only thing left to do is make use of the pipe. To access a pipe directly, the same system calls that are used for low-level file I/O can be used (recall that pipes are actually represented internally as a valid inode). To send data to the pipe, we use the write() system call, and to retrieve data from the pipe, we use the read() system call. Remember, low-level file I/O system calls work with file descriptors! However, keep in mind that certain system calls, such as lseek(), do not work with descriptors to pipes.
  8. Pipeparentchild.c
  9. pipe2waycomm.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> main() { int p1[2] = {0,0}, p2[2]; pipe(p1); pipe(p2); if(fork() == 0) { printf("CHILD PROCESS \n"); close(p1[0]); close(p2[1]); char cbuf[20] = ""; write(p1[1], "HAI FROM CHILD" , 20); read(p2[0] , cbuf , 20); printf("child read %s \n",cbuf); } else { printf("PARENT PROCESS \n"); close(p1[1]); close(p2[0]); char buffer[20]; buffer[read(p1[0] , buffer , 20)] = '\0'; printf("parent read : %s \n",buffer); write(p2[1] ,"BYE FROM PARENT \n", 20); } return 0; }
  10. We need to execute two commands (ls and wc). One process cannot execute two commands, we need to create child process. Assume child execute ls and passes the ouput to pipe, parent reads the input from pipe and execute wc. #include <stdio.h> #include <stdlib.h> #include <unistd.h> main() { int fd [2] = {0,0}, n; if( pipe( fd) == -1) { printf("can not create pipe \n"); return 1; } if(fork() == 0) { close(fd[0]); dup2(fd[1] , 1); execlp("ls","ls",0); } else { close(fd[1]); dup2(fd[0] , 0); execlp("wc","wc",0); } }
  11. main() { int fd [2] = {0,0}, n; if( pipe( fd) == -1) { printf("can not create pipe \n"); return 1; } if(fork() == 0) { close(fd[0]); dup2(fd[1] , 1); execlp("ls","ls","-l",0); } else { int fd1[2] = {0}; if(pipe(fd1) == -1) printf("Cannot create 2nd pipe "); if(fork() == 0) { close(fd[1]); close(fd1[0]); dup2(fd[0] , 0); dup2(fd1[1] , 1); execlp("head","head","-4",0); } else{ close(fd[0]); close(fd[1]); close(fd1[1]); dup2(fd1[0] , 0); execlp("tail","tail","-1",0); } } }
  12. main() { int fd [2] = {0,0}, n; if( pipe( fd) == -1) { printf("can not create pipe \n"); return 1; } if(fork() == 0) { close(fd[0]); dup2(fd[1] , 1); execlp("ls","ls","-l",0); } else { int fd1[2] = {0}; if(pipe(fd1) == -1) printf("Cannot create 2nd pipe "); if(fork() == 0) { close(fd[1]); close(fd1[0]); dup2(fd[0] , 0); dup2(fd1[1] , 1); execlp("head","head","-4",0); } else{ close(fd[0]); close(fd[1]); close(fd1[1]); dup2(fd1[0] , 0); execlp("tail","tail","-1",0); } } }
  13. Mknod can be used to create different device file. (p – pipe)
  14. int mknod(const char *path, mode_t mode, dev_t dev); mknod(“PIPE“   , S_IFIFO | 0666 , 0);
  15. #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> main() { int fd; printf("Retval mknod %d \n",mknod("mypipe",S_IFIFO | 0666 , 0)); if(fork() == 0) { fd = open("mypipe",O_WRONLY); printf("Child : Write mode : %d \n",fd); write(fd,"HELLO",5); } else { char buff[6] = ""; fd = open("mypipe",O_RDONLY); printf("Parent : Read mode : %d \n",fd); buff[read(fd , buff , 5)] = '\0'; printf("Message read = %s " , buff); } }
  16. First create a pipe using the following command. mkfifo mypipe ------------------------------------------------------------------------------------------ #include <stdio.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> int main() { char buff[50] = ""; int fd = open("mypipe",O_WRONLY); if(fd == -1){ printf("Pipe could not be opened \n"); exit(1); } printf("fd = %d \n",fd); printf("Enter the message to write : "); read(0, buff , 50); int r = write(fd , buff , strlen(buff)); printf("Number of bytes written = %d" , r); return 0; }