面试题答案
一键面试1. poll函数的数据结构
poll
函数使用pollfd
结构体数组来表示要监听的文件描述符集合。pollfd
结构体定义如下:
struct pollfd {
int fd; /* 文件描述符 */
short events; /* 等待的事件 */
short revents; /* 发生的事件 */
};
- fd:指定要监听的文件描述符。如果
fd
为负数,events
会被忽略,revents
会被清0。 - events:指定该文件描述符上等待的事件,它是一系列事件标志的按位或,如
POLLIN
(数据可读)、POLLOUT
(数据可写)、POLLERR
(错误)等。 - revents:由内核在函数返回时设置,指示该文件描述符上实际发生的事件,也是一系列事件标志的按位或。
2. 如何监听文件描述符集合
poll
函数的原型为:
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
- fds:指向
pollfd
结构体数组的指针,该数组包含了要监听的所有文件描述符及其相关信息。 - nfds:
fds
数组中元素的个数。 - timeout:指定等待事件发生的超时时间,单位为毫秒。如果
timeout
为0,poll
函数立即返回;如果timeout
为-1,poll
函数将无限期等待,直到有事件发生。
poll
函数通过遍历pollfd
结构体数组,对每个文件描述符进行监听。内核会检查每个文件描述符上是否发生了在events
字段中指定的事件。如果有事件发生,内核会在对应的revents
字段中设置相应的事件标志。
3. 事件触发机制
当poll
函数被调用时,内核开始检查pollfd
数组中每个文件描述符的状态。如果在timeout
时间内,某个文件描述符上发生了在events
中指定的事件,poll
函数将返回。返回值表示发生事件的文件描述符的个数,这些文件描述符的revents
字段会被设置为实际发生的事件。
- 如果返回值大于0,说明有文件描述符发生了事件。应用程序可以遍历
pollfd
数组,检查每个元素的revents
字段,以确定具体是哪些文件描述符发生了什么事件。 - 如果返回值为0,表示在
timeout
时间内没有任何文件描述符发生事件。 - 如果返回值为-1,表示发生了错误,如
errno
可能被设置为EINTR
(被信号中断)、EFAULT
(fds
指针无效)等,应用程序需要根据errno
进行相应处理。
poll
函数采用水平触发(Level Triggered, LT)机制。在水平触发模式下,只要文件描述符对应的缓冲区还有未读数据(对于读事件)或者缓冲区还有空间可写(对于写事件),就会一直触发相应的事件。这意味着应用程序需要及时处理事件,以避免多次触发相同的事件。