知识补给站

对文件描述符集合操作的四个宏操作

对文件描述符集合操作的四个宏操作在select函数中起着关键的作用,它们用于初始化、添加、删除和检查文件描述符集合中的元素。这四个宏为: FD_ZERO、FD_SET、FD_CLR、FD_ISSET:

FD_ZERO(fd_set *fdset)

  • 功能:清空文件描述符集合。

  • 参数:一个指向fd_set类型变量的指针。

  • 作用:将fdset指向的文件描述符集合中的所有位都设置为0,确保集合中没有包含任何文件描述符。

FD_SET(int fd, fd_set *fdset)

  • 功能:将一个文件描述符添加到文件描述符集合中。
  • 参数:一个整数fd,代表要添加的文件描述符;一个指向fd_set类型变量的指针。
  • 作用:将fdset指向的文件描述符集合中对应于fd的位设置为1,表示该集合包含文件描述符fd

FD_CLR(int fd, fd_set *fdset)

  • 功能:从文件描述符集合中删除一个文件描述符。
  • 参数:一个整数fd,代表要删除的文件描述符;一个指向fd_set类型变量的指针。
  • 作用:将fdset指向的文件描述符集合中对应于fd的位设置为0,表示该集合不再包含文件描述符fd

FD_ISSET(int fd, fd_set *fdset)

  • 功能:检查文件描述符集合中是否包含某个文件描述符。
  • 参数:一个整数fd,代表要检查的文件描述符;一个指向fd_set类型变量的指针。
  • 返回值:如果fdset指向的文件描述符集合中包含fd,则返回非零值(通常为1);否则返回0。
  • 作用:用于在select函数返回后,检查哪些文件描述符已经就绪(可读、可写或存在异常条件)。

服务器IO多路复用中的select和poll的区别

  1. 数据结构差异:
    (1)select:使用位图(bitmap)数据结构来存储被监听的文件描述符集合。这种数据结构在文件描述符数量较少时效率较高,但受限于位图的大小,通常能监听的文件描述符数量有限(通常在1024个左右,取决于系统和库的实现)。
    (2)poll:使用结构体数组(如pollfd)来存储被监听的文件描述符及其相关事件。这种数据结构允许监听更多的文件描述符,因为它不受位图大小的限制。
  2. 事件绑定:
    (1)select:没有将文件描述符和事件进行绑定。每次调用select时,都需要通过三个独立的文件描述符集合来指定要监听的可读、可写和异常事件。
    (2)poll:将文件描述符和事件直接绑定在pollfd结构体中,这使得编程接口更为简洁。在调用poll时,只需传递一个包含所有监听信息的pollfd数组即可。
  3. 数据拷贝:
    (1)select:在每次调用时,都需要将文件描述符集合从用户空间拷贝到内核空间,并在返回时将结果从内核空间拷贝回用户空间。这种频繁的数据拷贝在文件描述符数量较多时会导致性能下降。
    (2)poll:同样存在数据拷贝的问题,但由于poll使用结构体数组而不是位图,因此在某些情况下可能具有更高的效率。
  4. 时间复杂度:
    (1)select:在内核中无差别地遍历每个文件描述符,时间复杂度为O(n)。当文件描述符数量较大时,性能会受到显著影响。
    (2)poll:与select类似,也需要在内核中遍历每个文件描述符。但由于poll允许监听更多的文件描述符,因此在某些情况下可能具有更好的性能。
  5. 可重用性:
    (1)select:每次调用select时,都需要重新创建和设置文件描述符集合。这可能导致额外的编程开销。
    (2)poll:由于poll将文件描述符和事件绑定在结构体中,因此可以在多次调用之间重用相同的pollfd数组,从而减少了编程开销。