【Nginx】I/O多路转接之select、poll、epoll

从socket中读取数据可以使用如下的代码:

while( (n = read(socketfd, buf, BUFSIZE) ) >0)

if( write(STDOUT_FILENO, buf, n) = n)

{

printf(“write error”);

exit(1);

}

当代码中的socketfd描述符所对应的文件表项是处于阻塞时,它会一直阻塞,直到有数据从网络的另一端发送过来。如果它是一个服务器程序,它要读写大量的socket,那么在某一个socket上的阻塞很明显会影响与其它socket的交互过程。类似的问题不单单出现在网络上,还可以出现在读写加锁的文件和FIFO等等一系列的情况。

一种比较好的解决方法似乎是采用非阻塞IO来实现。把所要读取数据的socketfd设置为非阻塞状态,依次用read函数检查是否有数据到来,如有,它会返回接到数据的个数,否则它会返回-1以表示当前还没有数据到达。这样,对于每个socket,如有数据到来则读取,没有也会马上返回。这就是非阻塞IO的好处拉。部分代码如下:

//clientfd[] 为客户端的socket描述符组数,假设数组的大小为MAX,并且所有客户端socket描述符都设置为非阻塞状态时。

for(i = 0; i < MAX; ++i)

{

int n;

if( (n = read(clientfd[i], buf, SZIE)) >0)

{

//send response to client in here.

}

}

这里代码看起来与上面的代码没有太大的区别,其实是有很大的区别;区别就是使使用了非阻塞IO进行整个交互过程,使得各个客户端都得到相对平等的时间待遇。这种模式我们通常称为这“轮询”模式。轮询模式同样有它的不足之处,在执行read函数时,实际上大部分时间还是没有数据可读的,但仍不断地执行read,浪费了很多CPU时间。

实际,对于上述的问题,一种比较好的技术就是I/O多路转接(I/O multiplexing)。它可谓是上面两种方法的接衷:先构造一张有关描述符的数据表,然后调用一个函数,仅当有一个或多个描述符已准备可以进行IO操作时才返回,否则一直阻塞。在返回时,它会告诉进程那些描述符已准备好可以进行IO。

select函数

#include <sys/select.h>

int select(int maxfdp1,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *tvptr);

//返回准备就绪的描述符数,若超时则返回0,若出错则返回-1

?怎么知道哪些描述符已经准备就绪

描述符编号从0开始,maxfdp1是要检查的描述符数(从描述符0开始),readfds、writefds、exceptfds是指向描述符集的指针,每个描述符集存放在一个fd_set数据类型中,这种数据类型为每一个可能的描述符保持了一位。tvptr指定愿意等待的时间:

struct timeval{

  long tv_sec;//秒数

  long tv_uses;//微秒

};

poll函数

#include <poll.h>

int poll(struct pollfd fdarray[],nfds_t nfds,int timeout);//返回准备就绪的描述符数,若超时返回0,出错返回-1

pollfd结构数组的每个数组元素指定一个描述符编号以及对其所关心的状态

struct pollfd{

  int fd;

  short events;

  short revents;

};

效率与epoll效率基本相同

epoll模型的缺点:

1. 最大并发数限制,因为一个进程所打开的FD(文件描述符)是有限制的,由FD_SETSIZE设置,默认值是1024/2048,因此Select模型的最大并发数就被相应限制了。自己改改这个FD_SETSIZE?想法虽好,可是先看看下面吧…

2. 效率问题,select每次调用都会线性扫描全部的FD集合,这样效率就会呈现线性下降,把FD_SETSIZE改大的后果就是,大家都慢慢来,什么?都超时了??!!

3. 内核/用户空间 内存拷贝问题,如何让内核把FD消息通知给用户空间呢?在这个问题上select采取了内存拷贝方法。

参考:

http://blog.csdn.net/linyt/article/details/1722445

http://blog.csdn.net/sparkliang/article/details/4770655

【Nginx】I/O多路转接之select、poll、epoll

时间: 2024-10-09 23:25:35

【Nginx】I/O多路转接之select、poll、epoll的相关文章

高性能服务器——I/O多路转接的三种模式(select &poll& epoll)

一.简单的服务器I/O模型 最简单的的TCP服务器,有三种模式: 1.单执行流,一个server端连接一个client端 2.多进程,一个server端通过多进程的方式,每个进程连接一个client端 3.多线程,一个server端通过多进程的方式,每个线程连接一个client端 (http://zhweizhi.blog.51cto.com/10800691/1830267) 这里实现过 要提升服务器性能,其实就是想要让一个server端能在负载允许的情况下,连接尽可能多的client端. 因

I/O多路转接select/poll/epoll

I/O多路转接(多路复用)又被称为“事件驱动”,是操作系统提供的一个功能,当你关心的文件(如socket)可读.可写时(称为事件就绪)采用某种方式通知你,只有收到通知时你才去执行read/write操作,这样在每次读或写时就不会阻塞,即I/O操作中等的部分交给操作系统内核去完成,而read/write之类的操作只需要在事件就绪时完成数据拷贝.等的过程由select/poll/epoll等系统调用触发,这些函数可同时监视多个描述符上的事件是否就绪,因此可以在一个线程内不发生阻塞的交替完成多个文件的

Uwsgi Nginx Apache select poll epoll

uWSGI是一个Web服务器,它实现了WSGI协议.uwsgi.http等协议.Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换.要注意 WSGI / uwsgi / uWSGI 这三个概念的区分.WSGI是一种通信协议.uwsgi是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信.而uWSGI是实现了uwsgi和WSGI两种协议的Web服务器.uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of

Linux统系统开发12 Socket API编程3 TCP状态转换 多路IO高并发select poll epoll udp组播 线程池

[本文谢绝转载原文来自http://990487026.blog.51cto.com] Linux统系统开发12 Socket API编程3 TCP状态转换 多路IO高并发select  poll  epoll udp组播 线程池 TCP 11种状态理解: 1,客户端正常发起关闭请求 2,客户端与服务端同时发起关闭请求 3,FIN_WAIT1直接转变TIME_WAIT 4,客户端接收来自服务器的关闭连接请求 多路IO转接服务器: select模型 poll模型 epoll模型 udp组播模型 线

I/O多路复用之select,poll,epoll简介

一.select 1.起源 select最早于1983年出现在4.2BSD中(BSD是早期的UNIX版本的分支). 它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作. 2.select的优点 目前几乎在所有的平台上支持,具有良好的跨平台支持. 3.select的缺点 单个进程能够监视的文件描述符的数量存在最大限制.默认情况下,在Linux上单个进程能够打开的最

Linux内核中网络数据包的接收-第二部分 select/poll/epoll

和前面文章的第一部分一样,这些文字是为了帮别人或者自己理清思路的,而不是所谓的源码分析,想分析源码的,还是直接debug源码最好,看任何文档以及书都是下策.因此这类帮人理清思路的文章尽可能的记成流水的方式,尽可能的简单明了. Linux 2.6+内核的wakeup callback机制 Linux 内核通过睡眠队列来组织所有等待某个事件的task,而wakeup机制则可以异步唤醒整个睡眠队列上的task,每一个睡眠队列上的节点都拥有一个 callback,wakeup逻辑在唤醒睡眠队列时,会遍历

几种典型的服务器网络编程模型归纳(select poll epoll)

1.同步阻塞迭代模型 同步阻塞迭代模型是最简单的一种IO模型. 其核心代码如下: bind(srvfd); listen(srvfd); for(;;) { clifd = accept(srvfd,...); //开始接受客户端来的连接 read(clifd,buf,...); //从客户端读取数据 dosomthingonbuf(buf); write(clifd,buf)//发送数据到客户端 } 上面的程序存在如下一些弊端: 1)如果没有客户端的连接请求,进程会阻塞在accept系统调用处

select,poll,epoll的归纳总结区分

Select.Poll与Epoll比较 以下资料都是来自网上搜集整理.引用源详见文章末尾. 1 Select.Poll与Epoll简介 Select select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理.这样所带来的缺点是: 1 单个进程可监视的fd数量被限制 2 需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大 3 对socket进行扫描时是线性扫描 Poll poll本质上和select没有区别,它将用户传入的数组拷贝到内核

Linux下select&amp;poll&amp;epoll的实现原理(一)

最近简单看了一把Linux linux-3.10.25 kernel中select/poll/epoll这个几个IO事件检测API的实现.此处做一些记录.其基本的原理是相同的,流程如下 先依次调用fd对应的struct file.f_op->poll()方法(如果有提供实现的话),尝试检查每个提供待检测IO的fd是否已经有IO事件就绪 如果已经有IO事件就绪,则直接所收集到的IO事件返回,本次调用结束 如果暂时没有IO事件就绪,则根据所给定的超时参数,选择性地进入等待 如果超时参数指示不等待,则