Poll就是监控文件是否可读的一种机制,作用与select一样。
应用程序的调用函数如下:
int poll(struct pollfd *fds,nfds_t nfds, int timeout);
Poll机制会判断fds中的文件是否可读,如果可读则会立即返回,返回的值就是可读fd的数量,如果不可读,那么就进程就会休眠timeout这么长的时间,然后再来判断是否有文件可读,如果有,返回fd的数量,如果没有,则返回0.
使用非阻塞I/O的应用程序通常会使用select()和poll()系统调用查询是否可对设备进行无阻塞的访问,这两个系统调用最终又会引发设备驱动中的poll()函数被执行
如果当前不可读(先调用驱动.poll确定是否可读,然后继续do_poll),那么在sys_poll->do_poll中当前进程就会睡眠在等待队列上,这个等待队列是由驱动程序提供的(就是poll_wait中传入的那个)。当可读的时候,驱动程序可能有一部分代码运行了(比如驱动的中断服务
程序),那么在这部分代码中,就会唤醒等待队列上的进程,也就是之前睡眠的那个,当那个进程被唤醒后do_poll会再一次的调用驱动程序的poll函数,这个时候应用程序就知道是可读的了。
Demo程序(一个线程中同时监听两个UDP客户程序的数据发送):
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> /// Handle poll input types #define POLL_INPUT (POLLIN | POLLPRI) /// Handle poll error types #define POLL_ERROR (POLLERR | POLLHUP | POLLNVAL) /// Handle pool output types #define POLL_OUTPUT (POLLOUT) /// Identify each physical interface typedef enum FHandleVal { INTERFACE_UDP_DCP = 0, INTERFACE_UDP_LTE, INTERFACE_MAX_VAL } eFHandleVal; static struct pollfd FDesc[INTERFACE_MAX_VAL]; static int rxUDPLTEInit(); static int rxUDPDCPInit(); static int rxLteUDPData(int fd); static int rxDCPUDPData(int fd); int rxUDPLTEInit() { struct sockaddr_in server_lte_addr; /// UDP datagram socket int sock_Lte_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock_Lte_fd < 0) { // oops printf("UDP lte: RX socket failed %d, %s ", errno, strerror(errno)); sock_Lte_fd = -errno; return -1; } memset(&server_lte_addr,0,sizeof(struct sockaddr_in)); server_lte_addr.sin_family = AF_INET; server_lte_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_lte_addr.sin_port = htons(27358); int rc = bind(sock_Lte_fd, (struct sockaddr *)&server_lte_addr, sizeof(server_lte_addr)); if (rc < 0) { // oops printf("UDP: bind(%d, ANY) RX failed: %d, %s ", sock_Lte_fd, errno, strerror(errno)); close(sock_Lte_fd); sock_Lte_fd = -errno; } else { printf("UDP: bind on RX port %d ",27358); } return sock_Lte_fd; } int rxUDPDCPInit() { int sock_fd; struct sockaddr_in server_addr; struct sockaddr_in src_addr; socklen_t client_len; memset(&server_addr,0,sizeof(struct sockaddr_in)); if ((sock_fd = socket(AF_INET, SOCK_DGRAM,0)) < 0) { perror("socket create error "); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(4004); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); printf("Ready bind 4004 "); if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0) { perror("bind socket error. "); exit(1); } return sock_fd; } int rxDCPUDPData(int fd) { int rcv_num = -1; char rcv_buff[512]; struct sockaddr_in src_addr; socklen_t client_len; int encodeNum = -1; BSM_t BSMData; client_len = sizeof(struct sockaddr_in); rcv_num= recvfrom(fd, rcv_buff, sizeof(rcv_buff), 0, (struct sockaddr*)&src_addr, &client_len); if (rcv_num>0) { rcv_buff[rcv_num] = '