当在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
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
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