8/13/2019 Npc06
1/52
Chapter 6I/O Multiplexing:
select and poll function
8/13/2019 Npc06
2/52
abstract
Introduction
I/O Models(5)
Synchronous I/O versus Asynchronous I/O select function
batch input
shutdown function
pselect function
poll function
8/13/2019 Npc06
3/52
Introduction
TCP client is handling two inputs at the sametime: standard input and a TCP socket
when the client was blocked in a call to read, the
server process was killed
server TCP sends FIN to the client TCP, but the
client never see FIN since the client is blocked
reading from standard input
=> the capability to tell the kernel that we want to benotified if one or more I/O conditions are ready.
: I/O multiplexing (select and poll)
8/13/2019 Npc06
4/52
When:client is handling multiple descriptors (interactive
input and a network socket).
Client to handle multiple sockets(rare)
TCP server handles both a listening socket and its
connected socket.
Server handle both TCP and UDP.
Server handles multiple services and multipleprotocols
8/13/2019 Npc06
5/52
I/O Models
Blocking I/O nonblocking I/O
I/O multiplexing(select and poll)
signal driven I/O(SIGIO) asynchronous I/O(posix.1 aio_ functions)
Two distinct phases for an input operations
1. Waiting for the data to be ready
2. Copying the data from the kernel to the process
8/13/2019 Npc06
6/52
Blocking I/O
application
recvfrom
Process
datagram
System call
Return OK
No datagram ready
Datagram ready
copy datagram
Copy complete
kernel
Process blocks
in a call to
recvfrom
Wait for
data
Copy data
from kernel
to user
8/13/2019 Npc06
7/52
nonblocking I/Oapplication
recvfrom
Process
datagram
System call
Return OK
No datagram ready
copy datagram
application
kernel
Wait for
data
EWOULDBLOCK
recvfrom No datagram ready
EWOULDBLOCK
System call
recvfrom datagram readySystem call
Copy datafrom kernel
to user
Process
repeatedly
call recvfrom
wating for an
OK return(polling)
8/13/2019 Npc06
8/52
I/O multiplexing(select and poll)
application
select
Process
datagram
System call
Return OK
No datagram ready
Datagram ready
copy datagram
Copy complete
kernel
Wait for
data
Return readable
recvfrom
Copy data
from kernel
to user
Process block
in a call to
select waiting
for one of
possibly many
sockets to
become readable
Process blocks
while data
copied
into application
buffer
System call
i l d i / ( )
8/13/2019 Npc06
9/52
signal driven I/O(SIGIO)
application
Establish SIGIO
Process
datagram
System call
Return OK
Datagram ready
copy datagram
Copy complete
kernel
Wait for
data
Deliver SIGIO
recvfrom Copy datafrom kernel
to user
Process
continues
executing
Process blocks
while data
copied
into application
buffer
Sigaction system call
Return
Signal handler
Signal handler
8/13/2019 Npc06
10/52
asynchronous I/O
application
aio_read
Signal
handler
Process
datagram
System call
Delever signal
No datagram ready
Datagram ready
copy datagram
Copy complete
kernel
Process
continues
executing
Wait for
data
Copy data
from kernel
to user
Return
Specified in aio_read
8/13/2019 Npc06
11/52
Comparison of the I/O Models
blocking nonblockingI/O
multiplexing
signal-driven
I/O
asynchronous
I/O
initiate
complete
check
check
check
check
check
check
complete
bloc
ked
check
bl
ocked
ready
initiateblo
cked
complete
notification
initiateblo
cked
complete
initiate
notification
wait fordata
copy data
from kernel
to user
ist phase handled differently,2nd phase handled the same
handles both phases
8/13/2019 Npc06
12/52
Synchronous I/O , Asynchronous I/O
Synchronous I/O : cause the requesting process tobe blocked until that I/O operation (recvfrom)
completes.(blocking, nonblocking, I/O multiplexing,
signal-driven I/O)
Asynchronous I/O : does not cause the requesting
process to be blocked
(asynchronous I/O)
8/13/2019 Npc06
13/52
Select function
Allows the process to instruct the kernel to waitfor any one of 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.
(readable ,writable , expired time)
8/13/2019 Npc06
14/52
#include
#include
int select (int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
const struct timeval *);
struct timeval{long tv_sec; /* seconds */
long tv_usec; /* microseconds */
}
8/13/2019 Npc06
15/52
Condition of select function
Wait forever : return only descriptor isready(timeval = NULL)
wait up to a fixed amount of time:
Do not wait at all : return immediately afterchecking the descriptors(timeval = 0)
wait: normally interrupt if the process catches asignal and returns from the signal handler
8/13/2019 Npc06
16/52
8/13/2019 Npc06
17/52
Descriptor sets
Array of integers : each bit in each integercorrespond to a descriptor.
fd_set: an array of integers, with each bit in each integer corresponding to a
descriptor.
Void FD_ZERO(fd_set *fdset); /* clear all bits in fdset */
Void FD_SET(int fd, fd_set *fdset); /* turn on the bit for fd in fdset */
Void FD_CLR(int fd, fd_set *fdset); /* turn off the bit for fd in fdset*/
int FD_ISSET(int fd, fd_set *fdset);/* is the bit for fd on in fdset ? */
8/13/2019 Npc06
18/52
Example of Descriptor sets
function
fd_set rset;
FD_ZERO(&rset);/*all bits off : initiate*/
FD_SET(1, &rset);/*turn on bit fd 1*/FD_SET(4, &rset); /*turn on bit fd 4*/
FD_SET(5, &rset); /*turn on bit fd 5*/
8/13/2019 Npc06
19/52
specifies the number of descriptors to betested.
Its value is the maximum descriptor to be
tested, plus one.(hence our name of
maxfdp1)(example:fd1,2,5 => maxfdp1: 6)
constant FD_SETSIZE defined by
including , is the number of
descriptors in the fd_set datatype.(1024)
Maxfdp1 argument
C di i h k
8/13/2019 Npc06
20/52
Condition that cause a socket to
be ready for select
Condition Readable? writable? Exception?
Data to read
read-half of the connection closed
new connection ready for listening socket
Space available for writing
write-half of the connection closed
Pending error
TCP out-of-band data
8/13/2019 Npc06
21/52
could be blocked in the call to fgets when
something happened on the socket
blocks in a call to select instead, waiting for
either standard input or the socket to be readable.
on on an e y se ec nstr_cli(section5.5)
C di i h dl d b l i
8/13/2019 Npc06
22/52
Condition handled by select in
str_cli(section5.5)
Data of EOF
client
stdin
Socket
error EOF
RST
TCP
data FIN
Select for readability
on either standard
input or socket
ree con ons are an e
8/13/2019 Npc06
23/52
ree con ons are an ewith the socket
Peer TCP send a data,the socket becomr
readable and readreturns greater than 0
Peer TCP send a FIN(peer process terminates),
the socket become readable and readreturns
0(end-of-file)
Peer TCP send a RST(peer host has crashed and
rebooted), the socket become readable and
returns -1 and errnocontains the specific error
code
mp men a on o s r c
8/13/2019 Npc06
24/52
mp men a on o s r_cfunction usingselect
Void str_cli(FILE *fp, int sockfd)
{
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);
Continue..
8/13/2019 Npc06
25/52
if (FD_ISSET(sockfd, &rset)) { /* socket is readable */
if (Readline(sockfd, recvline, MAXLINE) == 0)
err_quit("str_cli: server terminated prematurely");
Fputs(recvline, stdout);
}
if (FD_ISSET(fileno(fp), &rset)) { /* input is readable */
if (Fgets(sendline, MAXLINE, fp) == NULL)
return; /* all done */
Writen(sockfd, sendline, strlen(sendline));}
}//for
}//str_cli
8/13/2019 Npc06
26/52
Stop and waitsends a line to the server
and then waits for the reply
request
request
serverrequest
request
serverreply
reply
reply
reply
client
time1
time2
time3
time4
time5
time6
time7
time0
8/13/2019 Npc06
27/52
Batch input
request8 request7 request6 request5
reply1 reply2 reply3 reply4
Time 7:
request9 request8 request7 request6
reply2 reply3 reply4 reply5
Time 7:
8/13/2019 Npc06
28/52
The problem with our revised str_cli functionAfter the handling of an end-of-file on input, the
send function returns to the main function, that is,
the program is terminated.
However, in batch mode, there are still otherrequests and replies in the pipe.
A way to close one-half of the TCP connection
send a FIN to the server, telling it we have finishedsending data, but leave the socket descriptor open
for reading
8/13/2019 Npc06
29/52
Shutdown function
Close one half of the TCP connection(example:send FIN to server, but leave the socket
descriptor open for reading)
Close function :
decrements the descriptors reference count and closes the
socket only if the count reaches 0,
terminate both direction(reading and writing)
Shutdown function : just one of them(reading or writing)
8/13/2019 Npc06
30/52
Calling shutdown to close half of a
TCP connection
client serverdata
data
FIN
Ack of data and FIN
data
data
FIN
Ack of data and FIN
Read returns > 0
Read returns > 0Read returns 0
write
writeclose
write
write
shutdown
Read returns > 0
Read returns > 0
Read returns 0
8/13/2019 Npc06
31/52
#includeint shutdown(int sockfd, int howto);
/* return : 0 if OK, -1 on error */
howto argumentSHUT_RD : read-half of the connection closed
SHUT_WR : write-half of the connection closedSHUT_RDWR : both closed
St li f ti i l t d
8/13/2019 Npc06
32/52
Str_cli function usingselect and
shutdown
#include "unp.h"void str_cli(FILE *fp, int sockfd)
{
int maxfdp1, stdineof;
fd_set rset;
char sendline[MAXLINE], recvline[MAXLINE];
stdineof = 0;
FD_ZERO(&rset);
for ( ; ; ) {
if (stdineof == 0) // select on standard input for readability
FD_SET(fileno(fp), &rset);
FD_SET(sockfd, &rset);
maxfdp1 = max(fileno(fp), sockfd) + 1;
Select(maxfdp1, &rset, NULL, NULL, NULL);
Continue..
8/13/2019 Npc06
33/52
if (FD_ISSET(sockfd, &rset)) { /* socket is readable */
if (Readline(sockfd, recvline, MAXLINE) == 0) {
if (stdineof == 1)
return; /* normal termination */
else
err_quit("str_cli: server terminated prematurely");
}
Fputs(recvline, stdout);
}
if (FD_ISSET(fileno(fp), &rset)) { /* input is readable */if (Fgets(sendline, MAXLINE, fp) == NULL) {
stdineof = 1;
Shutdown(sockfd, SHUT_WR); /* send FIN */
FD_CLR(fileno(fp), &rset);
continue;}
Writen(sockfd, sendline, strlen(sendline));
}
}}
8/13/2019 Npc06
34/52
TCP echo server Rewrite the server as a single process that uses
select to handle any number of clients, instead
of forking one child per client.
8/13/2019 Npc06
35/52
Data structure TCP server(1)
Client[]
[0]
[1]
[2]
-1
-1
-1
-1[FD_SETSIZE -1]
rset:
fd0 fd1 fd2 fd3
0 0 0 1
Maxfd + 1 = 4
fd:0(stdin),1(stdout),2(stderr)
fd:3 => listening socket fd
Before first client has established a connection
8/13/2019 Npc06
36/52
Data structure TCP server(2)
Client[]
[0]
[1]
[2]
4
-1
-1
-1[FD_SETSIZE -1]
rset:
fd0 fd1 fd2 fd3
0 0 0 1
Maxfd + 1 = 5
* fd3 => listening socket fd
fd4
1
*fd4 => client socket fd
After first client connection is established
8/13/2019 Npc06
37/52
Client[]
[0]
[1]
[2]
4
5
-1
-1[FD_SETSIZE -1]
rset:
fd0 fd1 fd2 fd3
0 0 0 1
Maxfd + 1 = 6
* fd3 => listening socket fd
fd4
1
* fd4 => client1 socket fd
fd5
1
* fd5 => client2 socket fd
Data structure TCP server(3)
After second client connection is established
8/13/2019 Npc06
38/52
Data structure TCP server(4)
Client[]
[0]
[1]
[2]
-1
5
-1
-1[FD_SETSIZE -1]
rset:
fd0 fd1 fd2 fd3
0 0 0 1
Maxfd + 1 = 6
* fd3 => listening socket fd
fd4
0
* fd4 => client1 socket fd deleted
fd5
1
* fd5 => client2 socket fd
*Maxfd does not change
After first client terminates its connection
TCP echo server using single
8/13/2019 Npc06
39/52
TCP echo server using single
process#include "unp.h"
int main(int argc, char **argv){
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, client[FD_SETSIZE];
ssize_t n;
fd_set rset, allset;char line[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
8/13/2019 Npc06
40/52
maxfd = listenfd; /* initialize */
maxi = -1; /* index into client[] array */
for (i = 0; i < FD_SETSIZE; i++)
client[i] = -1; /* -1 indicates available entry */
FD_ZERO(&allset);FD_SET(listenfd, &allset);
for ( ; ; ) {
rset = allset; /* structure assignment */
nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
#ifdef NOTDEF printf("new client: %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL),
ntohs(cliaddr.sin_port));
#endif
8/13/2019 Npc06
41/52
for (i = 0; i < FD_SETSIZE; i++)
if (client[i] < 0) {
client[i] = connfd; /* save descriptor */
break;
}
if (i == FD_SETSIZE)
err_quit("too many clients");
FD_SET(connfd, &allset); /* add new descriptor to set */
if (connfd > maxfd)
maxfd = connfd; /* for select */
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready
8/13/2019 Npc06
42/52
for (i = 0; i
8/13/2019 Npc06
43/52
Denial of service attacks
If Malicious client connect to the server,send 1 byte of data(other than a newline),
and then goes to sleep.
=>call readline, server is blocked.
8/13/2019 Npc06
44/52
Solution
use nonblocking I/O
have each client serviced by a separate thread of
control (spawn a process or a thread to serviceeach client)
place a timeout on the I/O operation
8/13/2019 Npc06
45/52
pselectfunction
#include
#include
#include
int pselect(int maxfdp1, fd_set *readset, fd_set *writeset,
fd_set *exceptset, const struct timespec *timeout,
const sigset_t *sigmask)
pselectfunction was invented by Posix.1g.
8/13/2019 Npc06
46/52
pselectfunction struct timespec{
time_t tv_sec; /*seconds*/
long tv_nsec; /* nanoseconds */
sigmask => pointer to a signal mask.
8/13/2019 Npc06
47/52
Poll function Similar to select, but provide additional
information when dealing with streams devices
#include
int poll(struct pollfd *fdarray, unsigned longnfds, int timeout);
/*return : count of ready descriptors, 0 on timeout,
-1 on error*/
8/13/2019 Npc06
48/52
Struct pollfd{int fd; /* descriptor to check */
short events; /* events of interest on fd */
short revents;/*events that occurred on fd*/}
specifies the conditions to be tested for a given
descriptor fd
events: the conditions to be tested
revents:the status of that descriptor
npu even s an re urne reven s
8/13/2019 Npc06
49/52
npu even san re urne reven sforpoll
ConstantInputto
events?
Resultfrom
revents?Description
POLLIN
POLLRDNORMPOLLRDBAND
POLLPRI
Normal or priority band data can be read
normal data can be readpriority band data can be read
high-priority data can be read
POLLOUT
POLLWRNORM
POLLWRBAND
POLLERR
POLLHUP
POLLNVAL
normal data can be written
normal data can be written
priority band data can be written
An error has occurred
hangup has occurred
descriptor is not an open file
8/13/2019 Npc06
50/52
Timeout value for poll
Timeoutvalue Description
INFTIM
0
>0
Wait forever
Return immediately, do not block
Wait specified number of milliseconds
If we are no longer interested inparticular descriptor, just set the fd
member of the pollfd structure
Specifies how long the function is to wait before returning
8/13/2019 Npc06
51/52
8/13/2019 Npc06
52/52