Home | | Network Programming and Management | I / O Multiplexing Model

Chapter: Network Programming and Management : Application Development

I / O Multiplexing Model

IN this select or poll functions are called instead of recvfrom. The summary of I/O Multiplexing call is given in the following figure:

I / O Multiplexing Model :


IN this select or poll  functions are called instead of recvfrom. The summary of I/O Multiplexing call is given in the following figure:


IN this the call to select is blocked waiting for the datagram socket to be readable. When select returns that the socket is readable, then the recvfrom called to copy the datagram into the application.

 

Compared to blocking model, the difference here is that the application can wait for more than one descriptors to be ready. The disadvantages is that select requires two system calls.

 

Signal Driven I/O Model

 

Signals are used to tell the kernel to notify applications with the SIGIO signal when the descriptor is ready. It is called signal driven I/O Model. The summary is shown in the following figure.

 

First enable the socket for the signal driven I/O and install a signal handler using the sigaction system call. The return from this system call is immediate and our process continuous, it is not block. When the datagram is ready to be ready, the SIGIO signal is generated for our process. We can either read the datagram from the signal handler by calling recvfrom and then notify the main loop that the data is ready to be process, or we can notify the main lop and let it read the datagram.

The advantage I this model is that we are not blocked while waiting for the datagram top arrive. The main loop can continue executing and just wait to be notified by the signal handler that either the dta is read to process or that the datagram is ready to be read.


Asynchronous I/O Model

 

Asynchronous I/O are new with the 1993 edition of Posix 1g. In this the kernel is told to start operation and to notify when the entire operation (including the copy of the data from the kernel to our buffer ) is over.

 

The main difference between this and the signal driven I/O model in the previous section is that with  the signal driven I/O the kernel  tells when the I/O operation can be initiated. But with asynchronous I/O, the kernel tells us when an  I/O operation is complete.  It is summarized as given below:


The function aio_read is called and the descriptor, buffer pointer, buffer size, file offset and how to notify when the entire operation is complete are passed to the kernel. The system calls returns immediately and our process is not blocked waiting for the I./O to complete. It is expected that the kernel will generate some signal when the operation is complete. The signal is generated only when the data is copied completely in the application buffer.

Comparison of the I/O Model


The main difference between the four models is the first phase as the second phase in the first four models is the same. The process is blocked in a cal to recvfrom while the data is copied from the kernel to the caller‘s buffer. Asynchronous I/O however, handles both the phases and is different form the first four.

 

Synchronous vs asynchronous:

 

A synchronous I/O operation causes the requesting process to be blocked until that I?O operation is completes.

 

An asynchronous I/O operation does not cause the requesting process to be blocked.

 

Based on this definition, the first four are synchronous as the actual I/O operation blocks the process. Only asynchronous I/O model matches the asynchronous I/O definition.

 

Select Function :

 

The select function allows the process to instruct the kernel to wait for any one of the multiple events to occur and to wake up the process only when one or more of these events occurs or when a specified amount of time has passed.

 

As an example, we can call  select and tell the kernel to return only

 

         any of the descriptors in the set { 1,4,5} are ready for reading, or

 

         any of the descriptors in the set {2,7} are ready for writing, or

 

 

         any of the descriptors in the set {1,4 } have an exception condition pending or

 

         after 10.2. seconds have elapsed.

That the kernel is told in what descriptors we are interested in (for reading, writing or an exception condition) and how long to wait. The descriptors in which we are interested are not restricted to sockets: any descriptor can be tested using select.

 

#include <sys/select.h> #include <sys/time.h>

 

int select (int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *excepset, const struct timeval *timeout); returns : positive count of ready descriptors, o on timeout, -1 on error.

Consider the final arguments: This tells the kernel how long to wait for one of the specified descriptors to become ready. A timeval structure specifies the number of seconds and microseconds.

 

Struct timeval

long  tv_sec;        /* seconds */

long  tv_usec;      /* micros seconds */

}                 

There are three possibilities:

         wait forever: return only when one of the specified descriptors is ready for I/O . For this, we specify the timeout argument as a null pointer.

 

         Wait upto a fixed amount of time: return when one of the specified descriptors is ready for I/O, but do not wait beyond the number of seconds and microseconds specified in the timeval structure pointer to by the timeout argument.

 

         Do not wait at all: return immediately after checking the descriptors. This is called polling. To specify this, the timeout argument must point to a timeval structure and the timer value must be zero

 

In case of first two scenario, the wait is normally interrupted if the process catches a signal and returns from the signal handler.

 

The const qualifier on the timeout argument means it is not modified by select on return. For example, if we specify a time limit of 10 sec, and select returns before the timer expires, with one or more descriptors ready or with an error of EINTR, the timeval structure is not updated with the number of seconds remaining when the functions returns.

 

The three middle arguments readset, writeset and excepset specify the descriptors that we want the kernel to test for reading, writing and exception conditions.

 

The two exceptions conditions currently supported are:

 

           The arrival of out of bound data for a socket.

 

         The control status information to be read from the master side of pseudo terminal

 

The maxfdp1 argument specifies the number of descriptors to be tested. Its value is the maximum descriptors to be tested plus one. The descriptors 0,1,2, through and including maxfdp1 –1 are tested. The constant FD_SETSIZE defined by including <sys /select.h>, is the number of descriptors in the fd_set

 

data type. It s value is often 1024, but few programs use that many descriptors. The maxfdp1 argument forces us to calculate the largest descriptors that we are interested in and then tell the kernel this value. For 1,4,5 the maxfdp1 is 6.

 

The design problem is how to specify one or more descriptors values for each of these three arguments. Select uses descriptor sets, typically an array of integers a32 by 32 array- of 1024 descriptors set. The descriptors are programmed for initializing /reading / writing and for closing using the following macros:

 

void FD_ZERO (fd_set  * fset)         /* clear all bits in fset */

void FD_SET (int fd,     fd_set          * fset)          /* Turn on the bit for fd in fset*/

void FD_CLR (int fd,    fd_set          * fset)          /*turn off the bit for fd in fset

void FD_ISSET (int fd,  fd_set  * fset)       /* is the bit for fd on in fset? */

For example to define a variable of type fd_set and then turn on the bits for descriptors, we write

fd_set rset;          

FD_ZERO (&rset);        /* initialize  the set; all bits to zet */

FD_SET (1, &rset);       /* turn on bit for fd 1

FD_SET (4, &rset );      /* turn on    bit for fd 4; */

If the descriptors are initialized to zero, unexpected results are likely to come.

 

Middle arguments to select, readset, writeset, or exceptset can be specified as null pointer, if we are not interest in that condition. The maxfdp1 arguments specifies the number of descriptors to be tested. Its value is the maximum descriptors to be tested, plus one (hence the name maxfdp1). The descriptors 0,1,2 up through and including maxfdp1 – 1 are tested.

 

Select function modifies the descriptor sets pointed by the readset, writset and excepset pointers. These three arguments are value-result arguments. When we call the function, we specify the values of the descriptors that we are interested in and on return the result indicates which descriptors are ready. We use FD_ISSET macros return to test a specific descriptor in an fd_set structure. Any descriptors that is not ready on return will have its corresponding bit cleared in the descriptors set.

 

str_cli Function :

The str_cli Function is rewritten using the select function as shown below:

# include ―unp.h‖

 

void str_cli (FILE *fp, int socket)

{

int     maxfdp1;

 

fd_set          rset;

char   sendline[MAXLINE],     recvline[MAXLINE];

FD_ZERO (&rset);

for ( ; ;)

{

FD_SET (fileno (fp), &rset);

FD_SET (sockfd, &rset);

maxfdp1 = max (fileno (fp), sockfd) + 1;

select (maxfdp1, &rset, NULL, NULL, NULL);

 

if (FD_ISSET(sockfd, &rset))

{        if (readline (sockfd, recvline, MAXLINE)==0)

 

err_quit (―str_cli: server terminated prematurely‖); fputs (recvline, stdout);

}

 

if (FD_ISSET(fileno(fp), &rset))

 

{if (fgets (sendline, MAXLINE, fp)==NULL) return;

 

writen(sockfd, sendline, strlen (sendline));

 

}

}

 

}

 

IN the above code the descriptors set is initialized to zero using FD_ZERO. Then, the descriptors, file pointer fp and socket sockfd are turned on using FD_SET. maxfdp1 is calculated from the descriptors list. Select function is called. IN this writeset pointer and exception set pointers are both NULL. Final time pointer is also NULL as the call is to be blocked until something is ready.

 

If on return from the select, socket is readable, the echoed line is read with readline and output by fputs.

 

If the standard input is readable, a line is read by fget sand written to the sockets using writen.

 

IN this although the four functions fgets, writen, readline and fputs are used, the order of flow within the function has changed. In this, instead of flow being driven by the call to fgets, it is driven by the call to select.

 

This has enhanced the robustness of the client.

 

Batch Input:

The echo client server, works in a stop and wait mode. That is , it sends a line to the server and then waits for the reply. This amount of time is one RTT (Round Trip Time) plus the server‘s processing time. If we consider the network between the client and the server as a full duplex pipe with requests from the client to server, and replies in the reverse direction, then the following shows the stop and wait mode.


The request is sent by the client at time 0 and we assume RTT of 8 units of time. The reply sent at a time 4 is received at time 7. It is assumed that there is no serving processing time and that the size of the request is the same as the reply. Also, TCP acknowledgment are ignored.

 

But as there is a delay between sending a packet and that packet        arriving at the other end of the pipe,

and since the pipe is full duplex, in this example we are only using one- eighth of the pipe capacity.

 

This stop and wait mode is fine for interactive input, but since our client reads from standard input and writes to standard output, we can easily run our client in a batch mode. When the input is redirected as in client server example, the output file is always same.

To see what is happening in the batch mode, we can keep sending requests as fast as the network can accept them. The server processes them and sends back the replies at the same rate. This leads to the full pipe at time 7 as shown below:


Filling the pipe between the client and the sever : batch Mode;

 

Now to understand the problem with the str_cli, let the input file contains only nine lines. The last line is sent at time 8 as shown above. But we cannot close the connection after writing this request, because there are still other requests and rep0les in the pipe. The cause of the problem is our handling of end of file on input. The function returns to the main function, which then terminates. But in a batch mode, an end of file on the input does not imply. That we have finished reading from the socket. There might still requests on the way to the server or replies on the way to back from the server.

 

What we need is a way to close one half of the TCP connection. That is we want to send FIN to the server, telling it we have finished sending data, but leave the socket descriptors for reading. This is done with the shutdown function.

 

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail
Network Programming and Management : Application Development : I / O Multiplexing Model |


Privacy Policy, Terms and Conditions, DMCA Policy and Compliant

Copyright © 2018-2024 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.