select、poll、epoll简单总结

select、poll、epoll简单总结

1.socket

socket用于表示进程间通信的特殊文件类型类型,其本质是内核借助缓冲区形成的伪文件。
socket = IP地址(唯一标识一台主机) + 协议 + 端口号(一台主机中唯一标识一个进程)

2. socket创建TCP的流程

在这里插入图片描述

3. select()/poll()/epoll()

在这里插入图片描述

3.1 select()

  1. select()函数原型
    int select(int nfds,			     // 监控的文件描述符集中最大的加一
    			fd_set* readfds,	     // 监控有读数据到达文件描述符集合
    			fd_set* writefds,        // 监控有写数据到达文件描述符集合
    			fd_set* exceptfds,       // 监控有异常数据到达文件描述符集合
    			struct timeval* timeout  // 定时阻塞监控时间:NULL永久等待,>0固定时间,=0立即返回
    			) 
    
  2. select()时间复杂度
    select监控时只会知道有I/O事件发生,但不知道具体时哪些流发生了哪些操作,所以需要对所有流进行轮询,所以select具有O(n)复杂度。
  3. select()总结
    select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:
    1、单个进程可监视的fd数量被限制,即能监听端口的大小有限。32位机默认是1024个。64位机默认是2048(具体数目可以cat /proc/sys/fs/file-max察看)。
    2、对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低:
    3、需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大(每次调用select时,fd_set会从用户态copy到内核态)。

3.2 poll()

  1. poll()函数原型

    int poll(struct pollfd *fds, // 事件结构体 
    		 nfds_t nfds, //个数
    		 int timeout // 阻塞事件
    		)
    
    struct pollfd{
    	int fd;       //文件描述符
    	short events; //监听的事件
    	short revents;//监控事件中满足条件返回的事件
    }
    
  2. poll()时间复杂度
    时间复杂度O(n)

  3. poll()总结
    1、 poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的。

    2、 poll为“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

3.3 epoll()

  1. epoll()函数原型
int epoll_create(int size);//功能(建树):创建一个epoll对象,返回该对象的文件描述符(这个描述符就代表这个epoll对象),size表示要监听的个数。
//功能(增删改节点):把一个socket以及这个socket相关的事件添加到这个epoll对象描述符中去,目的就是通过这个epoll对象来监视这个socket上数据的来往情况;
int epoll_ctl(int efpd,//epoll_create()返回的epoll对象描述符;
			  int op,  //op:动作。有添加、删除、修改 ,对应数字是1,2,3, -对应宏定义:EPOLL_CTL_ADD、EPOLL_CTL_DEL、EPOLL_CTL_MOD
			  int sockid, // 表示客户端连接
			  struct epoll_event *event //事件信息。EPOLL_CTL_ADD和EPOLL_CTL_MOD都会用到这个event参数里边的事件信息。
			  );

typedef union epoll_data {
    void *ptr;
     int fd;
     __uint32_t u32;
     __uint64_t u64;
 } epoll_data_t;//保存触发事件的某个文件描述符相关的数据

 struct epoll_event {
     __uint32_t events;      /* epoll event */
     epoll_data_t data;      /* User data variable */
 };

//功能: 阻塞一小段时间并等待事件发生,返回事件集合
int epoll_wait(int epfd,                  //epoll_create()返回的epoll对象描述符
			   struct epoll_event *events,//events:事件数组,表示此次epoll_wait调用可以收集到的maxevents个已经准备好的的读写事件
			   int maxevents,			  //events数组的长度
			   int timeout);              //阻塞等待的时长
  1. epoll()时间复杂度
    时间复杂度O(1)。
    epoll会把哪个流发生了怎样的I/O事件通知我们,所以我们说epoll实际上是事件驱动的。

  2. epoll()总结
    1、没有最大并发连接的限制,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口);

    2、效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。在实际的网络环境中,Epoll的效率就会远远高于select和poll。

    3、内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销。
    4、epoll有水平触发(EPOLLLT)和边沿触发(EPOLLET)两种触发模式,LT是默认的模式。

    LT模式下,只要这个fd还有数据可读,每次 epoll_wait都会返回它的事件,提醒用户程序去操作;
    而在ET模式中,它只会提示一次,直到下次再有数据流入之前都不会再提示了,无论fd中是否还有数据可读。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值