A Simple Client-Server Example
The client-server e.g. shown in fig 3.3 is used throughout
this chapter for illustration of the various methods of IPC.
(refer to fig. 3.3)
The client reads a filename from the standard input and writes it to the IPC channel.
The server reads this filename from the IPC channel and tries to open the file for reading.
If the server can open the file, it responds by reading the file and writing it to the IPC channel, otherwise the server responds with an ASCII error message stating that it can't open the file.
The client then reads from the IPC channel, writing what it receives to the standard output. If the file can't be read by the server, the client reads an error message from the IPC channel. Otherwise the client reads the content of the file.
The two dashed line in fig. 3.3, between the client and server, correspond to some form of IPC.
PIPES
Pipes available for all Unix system. A pipe provides a one-way flow of data. A pipe is created by the pipe system call.
int pipe(int *filedes)
Two file descriptors are returned -
1. filedes[0] which is open for reading.
2. filedes[1] which is open for writing.
Pipes are of little use within a single process, but here
is a simple e.g. that shows how they are created and used.
----------------------------------------------------------------------------
#include<unistd.h>
main()
{
int pipefd[2], n;
char buff[100];
if (pipe(pipefd) < 0)
err_sys("pipe error
1: ");
printf("read fd= %d, write
fd = %d\n", pipefd[0], pipefd[1]);
if (write(pipefd[1], "hello
world\n", 12) != 12)
err_sys("write error
2: ");
if ((n=read(pipefd[0], buff,
sizeof(buff))) <= 0)
err_sys("read error
3:");
write(1, buff, n);
exit(0);
}
--------------------------------------------------------------------------------
output should be:
hello world
read fd = 3, write fd = 4
A diagram of what pipe looks like in a single process is shown in fig. 3.4. A pipe has a finite size, always at least 4096 bytes. see fig 3.4
Pipes are typically used to communicate between two different processes in the following way. First, a process creates a pipe and then forks to create a copy of itself. see fig. 3.5
Next the parent process closes the read end of the pipe and the child process closes the write end of the pipe. This provides a one-way flow of data between the two processes as shown in fig 3.6
real e.g.
When a user enters a command such as
who | sort | lpr
to a Unix shell, the shell does the steps shown above to create three processes with two pipes between them. (who is a program that outputs the login names, terminal names, and login times of all users on the system. The sort program orders this list by login names, and lpr is a 4.3BSD program that sends the result to the line printer.) see figure 3.7
Note that all the pipes shown so far have all been unidirectional, providing a one-way flow of data only. When a two-way flow of data is desired, we must create two pipes and use one for each direction. The actual steps are:
1. create pipe1, create pipe 2
2. fork
3.parent closes read end of pipe 1
4. parent closes write end of pipe 2
5. child closes write end of pipe 1
6. child closes read end of pipe 2
This generate the pic shown in fig. 3.8