简介
在Linux系统中,poll和select是两种常用的I/O多路复用技术,它们都可以用来实现对多个文件描述符的监视,它们之间存在一些区别,本文将详细介绍这两个函数的区别以及各自的使用方法。
区别
1、底层实现
poll和select都是基于内核I/O事件通知机制实现的,但它们的底层实现方式略有不同。
- select:select函数通过系统调用与内核进行通信,将需要监视的文件描述符集合传递给内核,然后内核会将这些文件描述符中的可读、可写和异常状态事件返回给用户空间,select函数会一直阻塞,直到某个文件描述符上有事件发生或者超时。
- poll:poll函数也是通过系统调用与内核进行通信,但它与select的区别在于,poll函数允许用户空间一次性传递多个文件描述符,而不仅仅是一个集合,当某个文件描述符上有事件发生时,内核会将该文件描述符及其对应的事件类型返回给用户空间,poll函数同样会一直阻塞,直到某个文件描述符上有事件发生或者超时。
2、可处理的文件描述符数量
- select:select函数最多可以同时监视1024个文件描述符(包括标准输入、输出和错误流),如果需要监视更多的文件描述符,可以使用poll函数。
- poll:poll函数没有明确的文件描述符数量限制,但是由于其底层实现方式的局限性,实际可用的文件描述符数量可能会受到系统资源的限制,在处理大量文件描述符时,poll函数可能不如select函数高效。
3、兼容性
- select:select函数是POSIX标准的组成部分,因此在支持POSIX的平台上具有较好的兼容性,在某些不支持POSIX的平台上,select函数可能无法使用。
- poll:poll函数同样是POSIX标准的组成部分,因此具有较好的兼容性,与select函数相比,poll函数在某些平台下的实现可能存在差异,导致性能和兼容性方面的问题。
使用方法
1、使用select函数
以下是一个简单的使用select函数实现I/O多路复用的示例:
#include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <sys/select.h> #include <errno.h> int main() { fd_set readfds; struct timeval timeout; int ret; int max_fd = 0; int i; int fd; char buf[1024]; FD_ZERO(&readfds); max_fd = open("test.txt", O_RDONLY); FD_SET(max_fd, &readfds); timeout.tv_sec = 5; timeout.tv_usec = 0; while (1) { ret = select(max_fd + 1, &readfds, NULL, NULL, &timeout); if (ret == -1 && errno != EINTR) { perror("select error"); break; } else if (ret == -1 && errno == EINTR) { printf("select interrupted by signal "); continue; } else if (ret == 0) { printf("timeout "); continue; } else if (ret > 0) { if (FD_ISSET(max_fd, &readfds)) { ret = read(max_fd, buf, sizeof(buf)); if (ret > 0) { buf[ret] = '\0'; printf("read data: %s ", buf); } else if (ret == 0) { printf("connection closed "); close(max_fd); break; } else { perror("read error"); break; } } else { for (i = 3; i <= max_fd; i++) { if (FD_ISSET(i, &readfds)) { ret = read(i, buf, sizeof(buf)); if (ret > 0) { buf[ret] = '0'; printf("read data from file %d: %s ", i, buf); } else if (ret == 0) { printf("file %d closed ", i); close(i); FD_CLR(i, &readfds); } else { perror("read error"); break; } } else if (FD_ISSET(i, &readfds)) { printf("file %d is ready for writing ", i); } else if (FD_ISSET(i, &readfds)) { /* should not happen */} else if (FD_ISSET(i, &readfds)) {} /* ignore errors */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do nothing */} /* do anything else?*/ return 0; };```
原创文章,作者:K-seo,如若转载,请注明出处:https://www.kdun.cn/ask/121031.html