Download presentation
Presentation is loading. Please wait.
1
I/O Multiplexing Capability of tell the kernel that wants to be notified when one or more I/O conditions are ready. For example, I/O data is available. Select e poll
2
I/O Multiplexing When a client is handling multiple descriptors, interactive input When TCP server handles listening sockets and other connected sockets When the servers accepts requests from both TCP and UDP. When a server handles multiple service or multiple protocols
3
I/O Blocking I/O Non-blocking I/O I/O multiplexing Signal driven I/O
Asynchronous I/O
4
I/O Operation Two steps: Waiting for data to be ready
Copying the data from the kernel to the process
5
Blocking I/O
6
Nonblocking I/O Does not put process into the sleep state
Returns code EWOULDBLOCK Polling
7
Nonblocking I/O
8
Select
9
Signal driven I/O Request the kernel to notify with the signal SEGIO when event occurs Not non-blocking Recvfrom or main loop
10
Signal driven I/O
11
Asynchronous I/O Tells the kernel when start the operation
Kernell notifies when operation is completed including copy from the ketnel to the buffer
12
E/S assíncrona
13
I/O Type
14
select Tell the kernel to wake up the process either when a set of events happen or when a timeout happens The type of descriptor can be specified (reading, writing or exception)
15
select #include <sys/select.h> #include <sys/time.h>
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout); Returns: positive count of ready descriptors, 0 on timeout, –1 on error O readset, writeset e exceptset sao arrys ade bits e designam os descritores que devem ser verificados para leitura escrita e condicoes, Maxpd1 da o numero maximo de desciptors a serem testados struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ }; a
16
select Three Possibilities of wait:
Wait until descriptor is ready for I/O– null pointer specifies the timeout value Wait up to a fixed amount of time Do not wait beyond the time specified in timeval structure
17
select Two options for test of execution: Arrival of out-of band data
The presenc of control status information to be read from master side pf pseudo terminal
18
select descriptor set (array of integers) – each bit corresponds to a signal Four macros: void FD_ZERO(fd_set *fdset); void FD_SET(int fd, fd_set *fdset); void FD_CLR(int fd, fd_set *fdset); int FD_ISSET(int fd, fd_set *fdset);
19
select Select modifies the descriptor set of readset, writeset, excepetion (value-result arguments) Set all bits and check at return
20
Descriptors ready Conditions for a descriptor to be ready for reading if one of the following conditions is true: The number of bytes of data in the socket receive buffer is greater than or equal to the current size of the low-water mark for the socket receive buffer. The option SO_RCVLOWAT allows to set this parameter The read-half of the connection is closed (TCP connecton received a FIN). A read operation on the socket will not block, returns zero
21
Descriptors ready The socket is a listening socket and the number of completed connections is nonzero. An accept on the listening socket will not block A socket error is pending. A read operation on the socket will not block and will return an error. These pending errors can be fetched and cleared by calling getsockopt
22
Descriptors ready Conditions for a descriptor to be ready for writing if one of the following conditions is true: The number of bytes available space in the socket send buffer is greater than or equal to the current size of the low-water mark for the socket send buffer and either the socket is connected or it does not require a connections. The low-water marking can be set by using SO_SNDLOWAT The write half of the connection is closed. A write operation will generate SIGPIPE
23
Descriptors ready The write-half of the connection is closed. A write operation on the socket will generate a SIGPIPE A socket error is pending. A write operation will not block and will return an error A socket error is pending. A write operation will not block and will return an error. Calling getsockops for the SO_ERROR socket option will clear the error
24
Ready for select A UDP socket is always writable since no connection is required There is a limited number of descriptors per sockets
25
str_cli 1 #include "unp.h" 2 void 3 str_cli(FILE *fp, int sockfd) 4 {
4 { 5 char sendline[MAXLINE], recvline[MAXLINE]; 6 while (Fgets(sendline, MAXLINE, fp) != NULL) { 7 Writen(sockfd, sendline, strlen (sendline)); 8 if (Readline(sockfd, recvline, MAXLINE) == 0) 9 err_quit("str_cli:server terminated prematurely"); 10 Fputs(recvline, stdout); 11 } 12 }
26
str_cli
27
str_cli 1 #include "unp.h" 2 void 3 str_cli(FILE *fp, int sockfd) 4 {
5 int maxfdp1; 6 fd_set rset; 7 char sendline[MAXLINE], recvline[MAXLINE]; 8 FD_ZERO(&rset); 9 for ( ; ; ) { 10 FD_SET(fileno(fp), &rset); 11 FD_SET(sockfd, &rset); 12 maxfdp1 = max(fileno(fp), sockfd) + 1; 13 Select(maxfdp1, &rset, NULL, NULL, NULL); 14 if (FD_ISSET(sockfd, &rset)) { /* socket is readable */ 15 if (Readline(sockfd, recvline, MAXLINE) == 0) err_quit("str_cli: server terminated prematurely"); 17 Fputs(recvline, stdout); 18 } 19 if (FD_ISSET(fileno(fp), &rset)) { /* input is readable */ 20 if (Fgets(sendline, MAXLINE, fp) == NULL) return; /* all done */ 22 Writen(sockfd, sendline, strlen(sendline)); 23 } 24 } 25 } A versao anterior poderia ficar bloqueada no fget De 8 a 13 seta o selecet – so precisa verificar readability , fileno converte converte um ponteiro para um arquivo de i/O, calcula o maxino dos dois desciptors para argumento se o socket estiver ready a linha echaoada e mostrada no output pr fputs 19-23 – se o sstandard input estiver readable, a linha e lida e escrita no socket
28
str_cli Function fileno converts a pointer to na I/O file into a pointer to descritors. Both select and poll work only on descriptors Descriptors for writing and for exceptions are set null Flow is driven by select and not by fget anymore
29
Stop and wait mode
30
Batch mode
31
Close Limitations of the close operation:
close decrements the descriptor’s reference count and closes the socket only if the count reaches; close terminates both directions of data transfer, reading and writing. shutdown send a FIN segment Shutdown is useful quando se quer fechar em uma direcao paraum tipo de operacao nelson
32
shutdown
33
shutdown shutdown howto:
#include <sys/socket.h> int shutdown(int sockfd, int howto); Returns: 0 if OK, –1 on error shutdown howto: SHUT_RD – the read-half of the connection is closed; no more read data and socket receive buffer content is discarded. SHUT_WR – the write-half is closed. Any data currently in the socket send buffer will be sent , followed by TCP’s normal termination sequence SHUT_RDWR both read and write are closed.
34
str_cli (final version)
3 void str_cli(FILE *fp, int sockfd) 4 { 5 int maxfdp1, stdineof; 6 fd_set rset; 7 char buf[MAXLINE]; 8 int n; 9 stdineof = 0; 10 FD_ZERO(&rset); 11 for ( ; ; ) { 12 if (stdineof == 0) 13 FD_SET(fileno(fp), &rset); 14 FD_SET(sockfd, &rset); 15 maxfdp1 = max(fileno(fp), sockfd) + 1; 16 Select(maxfdp1, &rset, NULL, NULL, NULL); 17 if (FD_ISSET(sockfd, &rset)) { /* socket is readable */ 18 if ( (n = Read(sockfd, buf, MAXLINE)) == 0) { if (stdineof == 1) return; /* normal termination */ else err_quit("str_cli: server terminated prematurely"); 23 } 24 Write(fileno(stdout), buf, n); 25 } 26 if (FD_ISSET(fileno(fp), &rset)) { /* input is readable */ 27 if ( (n = Read(fileno(fp), buf, MAXLINE)) == 0) { stdineof = 1; Shutdown(sockfd, SHUT_WR); /* send FIN */ FD_CLR(fileno(fp), &rset); continue; 32 } 33 Writen(sockfd, buf, n); 34 } 35 } 36 } str_cli (final version) A flag stdineof e uma nova flag inicializada em 0, testa readability on standard input sempre que esta variavel for zero (5 a 8) 16-24 se eof e encontrado esta e a terminmacao ormal. Caso contraio o servido\r terminou prematuramente 25-33 quando eof e encontrado a variavel flag e setada e shutdown e enviado comn argumento shut_wr
35
TCP Echo server (1) Tem-se comop read descriptor set , com os standard input, standard output e erro e um array de integer que contem os descritores dos sockets conectados
36
TCP Echo server (2) Um cliente fez uma conexao – descritor 4
37
TCP Echo server (3) Um segundo cliente fe uma conexao – descriptor 5
38
TCP echo server (4) O cliente com descriptor 4 fez um close
39
TCP echo server (5) 2 int 3 main(int argc, char **argv) 4 {
5 int i, maxi, maxfd, listenfd, connfd, sockfd; 6 int nready, client[FD_SETSIZE]; 7 ssize_t n; 8 fd_set rset, allset; 9 char buf[MAXLINE]; 10 socklen_t clilen; 11 struct sockaddr_in cliaddr, servaddr; 12 listenfd = Socket(AF_INET, SOCK_STREAM, 0); 13 bzero(&servaddr, sizeof(servaddr)); 14 servaddr.sin_family = AF_INET; 15 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 16 servaddr.sin_port = htons(SERV_PORT); 17 Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); 18 Listen(listenfd, LISTENQ); 19 maxfd = listenfd; /* initialize */ 20 maxi = -1; /* index into client[] array */ 21 for (i = 0; i < FD_SETSIZE; i++) 22 client[i] = -1; /* -1 indicates available entry */ 23 FD_ZERO(&allset); 24 FD_SET(listenfd, &allset); ... Parte ususla do codigo
40
TCP echo server (6) ... 25 for ( ; ; ) {
rset = allset; /* structure assignment */ nready = Select(maxfd + 1, &rset, NULL, NULL, NULL); if (FD_ISSET(listenfd, &rset)) { /* new client conn */ 29 clilen = sizeof(cliaddr); 30 connfd = Accept(listenfd, (SA *) &cliaddr, &clilen); 31 for (i = 0; i < FD_SETSIZE; i++) if (client[i] < 0) { 33 client[i] = connfd; /* save descriptor */ 34 break; } 36 if (i == FD_SETSIZE) err_quit("too many clients"); 38 FD_SET(connfd, &allset); /* add new descriptor to set */ 39 if (connfd > maxfd) maxfd = connfd; /* for select */ 41 if (i > maxi) maxi = i; /* max index in client[] array */ 43 if (--nready <= 0) continue; /* no more readable descriptors */ }*/ if */ 26-27 – select waits for something to happen; eithe the establishment of a new client connection of the arrival rate, a FIN or an RST onan existing connection 28-45 – if th elistening sock is readable, a new connection has been established. We call accept and update our data structure accordingly. We use the first unused entry in the client array to record the connected socket. The number of ready descriptors is decremented and if it is zero we can avoid the nbext for looop. Let us use the return value from select to avoid checking descriptors that are not ready.
41
TCP echo server (7) ... 46 for (i = 0; i <= maxi; i++) { /* check all clients for data */ 47 if ( (sockfd = client[i]) < 0) 48 continue; 49 if (FD_ISSET(sockfd, &rset)) { 50 if ( (n = Read(sockfd, buf, MAXLINE)) == 0) { 51 /* connection closed by client */ 52 Close(sockfd); 53 FD_CLR(sockfd, &allset); 54 client[i] = -1; 55 } else 56 Writen(sockfd, buf, n); 57 if (--nready <= 0) break; /* no more readable descriptors */ 59 } 60 } 61 } /* end for */ 62 }/* end main */ 46-60 – a test is made for each existing client connection as to wheather or not its descriptor is in the descriptor set returned by select. If so, a line is read from the client and echoed back to the client. If the client closes the connection, readline returns 0 and the data structure is updated.
42
Denial of service Client sends a byte and go into sleep mode, server becomes blocked A server that accepts request from multiple server can not block given a request of a single client Potential solution: Use of non-blocking I/O Each client treated as individual thread of control Set timer to I/O operation
43
poll Similar to select but provide additional information
#include <poll.h> int poll (struct pollfd *fdarray, unsigned long nfds, int timeout); Returns: count of ready descriptors, 0 on timeout, –1 on error struct pollfd { int fd; /* descriptor to check */ short events; /* events of interest on fd */ short revents; /* events that occurred on fd */ }; Utiliza um array de agregados ao inves de arrays debits como no selsct Event envia a condicao e recebe responsta em revent Timeout diz quanto temo a funcao deve esperarantes de retornar
44
poll
45
poll Three types of data: TCP and UDP data are considered normal
priority band High priority TCP and UDP data are considered normal TCP out-of-band is considered priority band New connection at listenning socket can be considered either as normal or as priority band 20-24 – we use the
46
TCP echo server (with poll) (1)
1 #include "unp.h" 2 #include <limits.h> /* for OPEN_MAX */ 3 int 4 main(int argc, char **argv) 5 { 6 int i, maxi, listenfd, connfd, sockfd; 7 int nready; 8 ssize_t n; 9 char buf[MAXLINE]; 10 socklen_t clilen; 11 struct pollfd client[OPEN_MAX]; 12 struct sockaddr_in cliaddr, servaddr; 13 listenfd = Socket(AF_INET, SOCK_STREAM, 0); 14 bzero(&servaddr, sizeof(servaddr)); 15 servaddr.sin_family = AF_INET; 16 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 17 servaddr.sin_port = htons(SERV_PORT); 18 Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); 19 Listen(listenfd, LISTENQ); 20 client[0].fd = listenfd; 21 client[0].events = POLLRDNORM; 22 for (i = 1; i < OPEN_MAX; i++) 23 client[i].fd = -1; /* -1 indicates available entry */ 24 maxi = 0; /* max index into client[] array */
47
TCP echo server (withpoll) (2)
... 25 for ( ; ; ) { 26 nready = Poll(client, maxi + 1, INFTIM); 27 if (client[0].revents & POLLRDNORM) { /* new client conn */ 28 clilen = sizeof(cliaddr); 29 connfd = Accept(listenfd, (SA *) &cliaddr, &clilen); 30 for (i = 1; i < OPEN_MAX; i++) 31 if (client[i].fd < 0) { 32 client[i].fd = connfd; /* save descriptor */ 33 break; 34 } 35 if (i == OPEN_MAX) 36 err_quit("too many clients"); 37 client[i].events = POLLRDNORM; 38 if (i > maxi) 39 maxi = i; /* max index in client[] array */ 40 if (--nready <= 0) 41 continue; /* no more readable descriptors */ 42 }
48
TCP echo server (with poll) (3)
43 for (i = 1; i <= maxi; i++) { /* check all clients for data */ 44 if ( (sockfd = client[i].fd) < 0) 45 continue; 46 if (client[i].revents & (POLLRDNORM | POLLERR)) { 47 if ( (n = read(sockfd, buf, MAXLINE)) < 0) { if (errno == ECONNRESET) { /* connection reset by client */ Close(sockfd); client[i].fd = -1; } else err_sys("read error"); 54 } else if (n == 0) { /* connection closed by client */ Close(sockfd); client[i].fd = -1; 58 } else Writen(sockfd, buf, n); 60 if (--nready <= 0) break; /* no more readable descriptors */ 62 } 63 } 64 } 65 }
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.