What does select mean in I/O multiplexing?

PHPz
Release: 2023-05-13 17:31:12
forward
1344 people have browsed it

select是用于监视多个文件描述符状态的变化的。即用来监视文件描述符读/写/异常状态是否就绪。

函数原型:int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);

select的几大缺点:

(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

(3)select支持的文件描述符数量太小了

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<unistd.h>
  5 #include<sys/select.h>
  6 
  7 int main()
  8 {
  9     int std_in = 0;
 10 //  int std_out = 1;
 11     fd_set reads;
 12 //  fd_set writes;
 13     //int max_nums = std_out;
 14     int max_nums = std_in;
 15     FD_ZERO(&reads);
 16 //  FD_ZERO(&writes);
 17     FD_SET(std_in,&reads);
 18 //  FD_SET(std_out,&writes);
 19     struct timeval _timeout = {5,0};
 20     int done = 0;
 21     while(!done)
 22     {
 23         _timeout.tv_sec = 5;
  24         _timeout.tv_usec = 0;
 25         //switch(select(max_nums+1,&reads,&writes,NULL,&_timeout))
 26         switch(select(max_nums+1,&reads,NULL,NULL,&_timeout))
 27         {
 28             case -1:
 29                 perror("select");
 30                 break;
 31             case 0:
 32                 printf("timeout...\n");
 33                 break;
 34             default://success
 35                 {
 36                     if(FD_ISSET(std_in,&reads))
 37                     {//read
 38                         char buf[1024];
 39                         memset(buf,&#39;\0&#39;,sizeof(buf));
 40                         ssize_t size = read(std_in,buf,sizeof(buf)-1);
 41                         if(size<0)
 42                         {
 43                             perror("read");
 44                             exit(1);
 45                         }
 46                         if(strncmp(buf,"quit",4)==0)
  47                         {
 48                             done =1;
 49                             continue;
 50                         }
 51                         printf("echo: %s",buf);
 52 
 53                     }
 54                 //  if(FD_ISSET(std_out,&writes))
 55                 //  {//writes
 56                 //      char buf[1024];
 57                 //      while(1)
 58                 //      {
 59                 //          memset(buf,&#39;\0&#39;,sizeof(buf));
 60                 //          strcpy(buf,"hello world");
 61                             //write(1,buf,sizeof(buf)-1);
 62                 //          printf("%s\n",buf);
 63                 //      }
 64                 //  }
 65                     break;
 66                 }
 67         }
 68     }
 69     return 0;
 70 }
 [fbl@localhost select]$ ./select 
hello
echo: hello
hi
echo: hi
nihao
echo: nihao
ahhau
echo: ahhau
quit
[fbl@localhost select]$
Copy after login
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<unistd.h>
  5 #include<sys/socket.h>
  6 #include<sys/select.h>
  7 #include<sys/types.h>
  8 #include<netinet/in.h>
  9 #include<arpa/inet.h>
 10 #include<assert.h>
 11 
 12 #define _BACKLOG_ 5
 13 int fd[64];
 14 void usage(char *_port)
 15 {
 16     printf("%s,[ip],[port]\n",_port);
 17 }
 18 int startup(char *ip,int port)
 19 {
 20     assert(ip);
 21     int sock = socket(AF_INET,SOCK_STREAM,0);
 22     if(sock<0)
 23     {
 24         perror("socket");
 25         exit(1);
 26     }
 27     struct sockaddr_in local;
 28     local.sin_family = AF_INET;
 29     local.sin_port = htons(port);
 30     local.sin_addr.s_addr = inet_addr(ip);
 31     if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
 32     {
 33         perror("bind");
 34         exit(2);
 35     }
 36     if(listen(sock,_BACKLOG_)<0)
 37     {
 38         perror("listen");
 39         exit(3);
 40     }
 41     return sock;
 42 
 43 
 44 }
 45 int main(int argc,char *argv[])
 46 {
 47     if(argc!=3)
 48     {
 49         usage(argv[0]);
 50         return 1;
 51     }
 52     int port = atoi(argv[2]);
 53     char *ip = argv[1];
 54     int listen_sock = startup(ip,port);
 55     int new_sock = -1;
 56     struct sockaddr_in client;
 57     socklen_t len = sizeof(client);
 58     fd_set reads;
 59     fd_set writes;
 60     int max_nums;
 61     struct timeval _timeout = {5,0};
 62     int done = 0;
 63     int i =0;
 64     int fd_nums = sizeof(fd)/sizeof(fd[0]);
 65     for(;i<fd_nums;++i)
 66     {
 67         fd[i]=-1;
 68     }
 69     fd[0] = listen_sock;
  70     while(!done)
 71     {
 72         _timeout.tv_sec = 5;
 73         _timeout.tv_usec = 0;
 74         FD_ZERO(&reads);
 75         FD_ZERO(&writes);
 76         for(i=0;i<fd_nums;++i)
 77         {
 78             if(fd[i]>0)
 79             {
 80                 FD_SET(fd[i],&reads);
 81                 if(fd[i]>max_nums)
 82                 {
 83                     max_nums = fd[i];
 84                 }
 85 
 86             }
 87         }
 88         switch(select(max_nums+1,&reads,&writes,NULL,&_timeout))
 89         {
 90             case -1:
 91                 perror("select");
 92                 break;
 93             case 0:
 94                 printf("timeout...\n");
 95                 break;
 96             default:
 97                 {
 98 
 99                     for(i=0;i<fd_nums;++i)
100                     {
101                         if(fd[i]==listen_sock && FD_ISSET(fd[i],&reads))
102                         {
103                             new_sock = accept(listen_sock,(struct sockaddr*)    &client,&len);
104                             if(new_sock<0)
105                             {
106                                 perror("accept");
107                                 continue;
108                             }
109                             for(i=0;i<fd_nums;++i)
110                             {
111                                 if(fd[i]==-1)
112                                 {
113                                     fd[i]=new_sock;
114                                 }
115                             }
116 
117                         }
118                         else if(fd[i]>0 && FD_ISSET(fd[i],&reads))
119                         {
120                             char buf[1024];
121                             memset(buf,&#39;\0&#39;,sizeof(buf));
122                             ssize_t size = read(new_sock,buf,sizeof(buf)-1);
123                             if(size<0)
124                             {
125                                 perror("read");
126                                 exit(4);
127                             }
128                             else if(size==0)
129                             {
130                                 printf("client close...\n");
131                                 close(fd[i]);
132                                 fd[i]=-1;
133                             }
134                             else
135                             {
136                                 buf[size]=&#39;\0&#39;;
137                             }
138                             printf("client:%s\n",buf);
139                         }
140                         else
141                         {}
142                     }
143 
144                     break;
145                 }
146 
147         }
148     }
149     return 0;
150 }

1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<unistd.h>
  5 #include<sys/socket.h>
  6 #include<sys/select.h>
  7 #include<sys/types.h>
  8 #include<netinet/in.h>
  9 #include<arpa/inet.h>
 10 void usage(char *_port)
 11 {
 12     printf("%s,[ip],[port]\n",_port);
 13 }
 14 int main(int argc,char *argv[])
 15 {
 16     if(argc!=3)
 17     {
 18         usage(argv[0]);
 19         return 1;
 20     }
 21     int port = atoi(argv[2]);
 22     char *ip = argv[1];
 23     int sock = socket(AF_INET,SOCK_STREAM,0);
 24     if(sock<0)
 25     {
 26         perror("socket");
 27         exit(1);
 28     }
 29     struct sockaddr_in remote;
 30     remote.sin_family = AF_INET;
 31     remote.sin_port = htons(port);
 32     remote.sin_addr.s_addr = inet_addr(ip);
 33     int ret = connect(sock,(struct sockaddr*)&remote,sizeof(remote));
 34     if(ret<0)
 35     {
 36         perror("connect");
 37         exit(1);
 38     }
 39     char buf[1024];
 40     while(1)
 41     {
 42 
 43         memset(buf,&#39;\0&#39;,sizeof(buf));
 44         printf("please say:");
 45         scanf("%s",buf);
 46         ssize_t size = write(sock,buf,sizeof(buf)-1);
  47         if(size<0)
 48         {
 49             perror("write");
 50             exit(2);
 51         }
 52         else if(size ==0)
 53         {}
 54         else
 55         {
 56             printf("client : %s\n",buf);
 57         }
 58     }
 59     return 0;
 60 }
[fbl@localhost select_socket]$ ./server 192.168.1.106 8080
timeout...
client:hello
client:hi
client:huowo
client close...
client:
read: Bad file descriptor
[fbl@localhost select_socket]$ 
[fbl@localhost select_socket]$ ./client 192.168.1.106 8080
please say:hello
client : hello
please say:hi
client : hi
please say:huowo
client : huowo
please say:^C
[fbl@localhost select_socket]$
Copy after login

The above is the detailed content of What does select mean in I/O multiplexing?. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:yisu.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!