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]);
}
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 );
}
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).
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
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
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);
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?
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);
}
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).
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);
}
}
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.
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);
}
}
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;
}