博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

关于FIONREAD命令的作用

Posted on 2009-12-21 13:28  Frisch' Blog  阅读(10829)  评论(0编辑  收藏  举报

当在ioctl里使用FIONREAD时,除了获得所指定的读缓存大小以外,还有清除设备准备就绪状态的作用.

 

代码
 1 #include <sys/types.h>
 2 #include <sys/time.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 #include <sys/ioctl.h>
 6 #include <unistd.h>
 7 
 8 int main(int argc, char* argv[])
 9 {
10     int debug = 0;
11     char buffer[128];
12     int result, nread;
13     fd_set inputs, testfds;
14     struct timeval timeout;
15     int status;
16     int* ptr = &inputs;
17     
18     FD_ZERO(&inputs);
19     printf("-----------------before SET-----%d-----------\n"*ptr);
20     FD_SET(0&inputs);
21     printf("-----------------after SET-----%d-----------\n"*ptr);
22     
23     
24     while(1)
25     {
26         
27         timeout.tv_sec = 2;
28         timeout.tv_usec = 500000;
29         
30         testfds = inputs;
31         ptr = &testfds;
32         result = select(FD_SETSIZE, &testfds, (fd_set*)NULL,
33                                         (fd_set*)NULL, /*&timeout*/0);
34         printf("==========================================\n");                                        
35         
36         sleep(4);
37         switch(result)
38         {
39             case 0:
40                 printf("timeout \n");
41                 debug = FD_ISSET(0&testfds);
42                 printf("t-----------------before SET-----%d----FD_SET--%d-----\n"*ptr, debug );
43                 break;
44             case -1:
45                 perror("select\n");
46                 exit(1);
47             default:
48                 if(FD_ISSET(0&testfds))
49                     {
50                         printf("1-----------------before SET-----%d-----------\n"*ptr);
51                         //ioctl(0, FIONREAD, &nread);
52                         if(0 == nread)
53                             {
54                                 printf("keyboard done \n");
55                                 exit(0);
56                             }
57                             printf("-----------result--%d----------\n", result);
58                             nread = read(0, buffer, nread);
59                             buffer[nread] = 0;
60                             printf("read %d from keyboard: %s\n", nread, buffer);
61                             
62                             printf("1-----------------after SET-----%d-----------\n"*ptr);
63                     }
64                 break;
65         }
66         
67     }
68     return 0;
69 }
70  

 

 

当51行注释以后, 由于各个设备的状态未被清除,所以循环一直处于非阻塞的状态.不停的打印一个状态(即未清除状态)的信息.

如果不注释ioctl,那么select会自动清除未准备好的设备状态. 此时阻塞是有效地.

 

同样的,在socket当中使用select和ioctl时测试结果也是如此:

 

代码
  1 /*  For our final example, server5.c, 
  2     we include the sys/time.h and sys/ioctl.h headers in place of signal.h
  3     in our last program and declare some extra variables to deal with select.  */
  4 
  5 #include <sys/types.h>
  6 #include <sys/socket.h>
  7 #include <stdio.h>
  8 #include <netinet/in.h>
  9 #include <sys/time.h>
 10 #include <sys/ioctl.h>
 11 #include <unistd.h>
 12 
 13 int main()
 14 {
 15     FILE* fp;
 16     int i=0;
 17     int count = 0;
 18     int server_sockfd, client_sockfd;
 19     int server_len, client_len;
 20     struct sockaddr_in server_address;
 21     struct sockaddr_in client_address;
 22     int result;
 23     fd_set readfds, testfds;
 24 
 25 /*  Create and name a socket for the server.  */
 26 
 27     server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
 28 
 29     server_address.sin_family = AF_INET;
 30     server_address.sin_addr.s_addr = htonl(INADDR_ANY);
 31     server_address.sin_port = htons(9734);
 32     server_len = sizeof(server_address);
 33 
 34     bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
 35 
 36 /*  Create a connection queue and initialize readfds to handle input from server_sockfd.  */
 37 
 38     listen(server_sockfd, 5);
 39   printf("-----------------server_socket----------%d----------\n", server_sockfd);
 40 
 41     FD_ZERO(&readfds);
 42     FD_SET(server_sockfd, &readfds);
 43     
 44     if(FD_ISSET(server_sockfd, &readfds))
 45     {
 46         printf("fds hit!\n");
 47     }
 48 
 49 /*  Now wait for clients and requests.
 50     Since we have passed a null pointer as the timeout parameter, no timeout will occur.
 51     The program will exit and report an error if select returns a value of less than 1.  */
 52 
 53     while(1) {
 54         char ch;
 55         int fd;
 56         int nread;
 57 
 58         testfds = readfds;
 59         
 60         printf("server waiting\n");
 61         result = select(FD_SETSIZE, &testfds, (fd_set *)0
 62             (fd_set *)0, (struct timeval *0);
 63 
 64         if(result < 1) {
 65             perror("server5");
 66    //         return 0;
 67         }
 68         
 69         
 70         
 71         printf("\\\\\\\\%d--------result---%d--\n", count, result);
 72                
 73 
 74 /*  Once we know we've got activity,
 75     we find which descriptor it's on by checking each in turn using FD_ISSET.  */
 76             count++;
 77             fp = fopen("count.txt""ab+");
 78                     for( i=0; i < FD_SETSIZE; i++)
 79                     {
 80                         if(FD_ISSET(i, &testfds))
 81                             fprintf(fp, "testfds ## count--%d------i:----%d-------\n", count, i);
 82                         if(FD_ISSET(i, &readfds))
 83                             fprintf(fp, "readfds ## count--%d------i:----%d-------\n", count, i);
 84                     }
 85                     fprintf(fp, "\n");
 86                     fclose(fp);
 87                     
 88                     
 89         for(fd = 0; fd < FD_SETSIZE; fd++) {
 90             //printf("count++++%d+++++++++++++++++++fd+++%d+++++++++++++++\n", count, fd);
 91             if(FD_ISSET(fd,&testfds)) {
 92 
 93 /*  If the activity is on server_sockfd, it must be a request for a new connection
 94     and we add the associated client_sockfd to the descriptor set.  */
 95                             
 96                             printf("*****count*******%d******************fd******%d***********\n", count, fd);
 97 
 98                 if(fd == server_sockfd) {
 99                     client_len = sizeof(client_address);
100                     client_sockfd = accept(server_sockfd, 
101                         (struct sockaddr *)&client_address, &client_len);
102                     
103                     FD_SET(client_sockfd, &readfds);
104                     
105                fp = fopen("debug.txt""ab+");
106                     for( i=0; i < FD_SETSIZE; i++)
107                     {
108                         if(FD_ISSET(i, &readfds))
109                             fprintf(fp, "serv ## count--%d------i:----%d-------\n", count, i);
110                     }
111                     fprintf(fp, "-----------serv---------------\n");
112                     fclose(fp);
113                     
114                     printf("adding client on fd %d\n", client_sockfd);
115                 }
116 
117 /*  If it isn't the server, it must be client activity.
118     If close is received, the client has gone away and we remove it from the descriptor set.
119     Otherwise, we 'serve' the client as in the previous examples.  */
120 
121                 else {
122                     fp = fopen("debug.txt""ab+");
123                     for( i=0; i < FD_SETSIZE; i++)
124                     {
125                         if(FD_ISSET(i, &readfds))
126                             fprintf(fp, "before ## count--%d------i:----%d-------\n", count, i);
127                     }
128                     fprintf(fp, "-----------before---------------\n");
129                     fclose(fp);
130                     
131                  // ioctl(fd, FIONREAD, &nread);
132                     
133                     
134 
135                     if(nread == 0) {
136                         close(fd);
137                         FD_CLR(fd, &readfds);
138                         printf("removing client on fd %d\n", fd);
139                     }
140 
141                     else {
142                         read(fd, &ch, 1);
143                         sleep(5);
144                         printf("serving client on fd %d\n", fd);
145                         ch++;
146                       //write(fd, &ch, 1);
147                                                 printf("serving 000on fd %d\n", fd);
148                     }
149                     
150                     fp = fopen("debug.txt""ab+");
151                     for(i=0; i < FD_SETSIZE; i++)
152                     {
153                         if(FD_ISSET(i, &readfds))
154                             fprintf(fp, "after ## count--%d------i:----%d-------\n", count, i);
155                     }
156                     fclose(fp);
157                 }
158                 fp = fopen("debug.txt""ab+");
159                     fprintf(fp, "\n\n");
160                     fclose(fp);
161             }
162         }
163     }
164 }
165