select是系统提供的一个多路转接接口,用于同时监视多个文件描述符(file descriptors)的状态变化。它允许程序等待多个文件描述符中的任意一个发生事件(如可读、可写或异常),从而实现高效的I/O操作。
select的核心工作是等待,直到被监视的文件描述符中有一个或多个事件就绪。其函数原型如下:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
- nfds:需要监视的文件描述符中最大值加1。 - eadfds、`writefds`、`exceptfds`:分别用于监视读、写和异常事件的文件描述符集合。 - `timeout`:设置`select`的等待时间,可以为阻塞等待(`NULL`)、非阻塞等待(`0`)或超时等待。
1. 初始化服务器,创建监听套接字并绑定端口。 2. 定义一个数组保存所有需要监视的文件描述符,并将监听套接字加入其中。 3. 在循环中调用select,监视文件描述符的读事件。 4. 如果监听套接字的读事件就绪,调用`accept`接受客户端连接。 5. 如果其他文件描述符的读事件就绪,调用`read`读取数据。
缺点:
- 每次调用`select`都需要遍历所有文件描述符集合,效率较低。 - 文件描述符数量受限于`FD_SETSIZE`,通常为1024。
六、总结 select是一种经典的I/O多路转接技术,适用于对性能要求不高但需要同时处理多个I/O事件的场景。然而,随着`poll`和`epoll`等更高效的技术出现,`select`在高并发场景下的局限性逐渐显现。