全部博文(290)
分类: C/C++
2011-12-25 01:43:26
同时有多个IO操作的情况下。异步I/O,又称为non-blocking I/0,是指程序的运行不需要等待IO完成之后才能够继续进行。(Asynchronous I/O, or non-blocking I/O, is a form of input/output processing that permits other processing to continue before the transmission has finished.)。
而同步I/O(也称为blocking I/O),程序运行需等待IO完成之后才能继续,在等待的这段时间可能被OS挂起(idle)。这样当该程序包含多个IO操作的话,程序运行的很大部分时 间浪费在了I/O等待上。比较常见的时候基于socket的server程序,如果采用同步的blocking mode,则无法有效地响应多个并发的client请求。
异步IO模型可以有效地提高程序的throughput, latency, responsiveness.
参考:, (how to configure operating systems and write code to support thousands of clients.)
异步IO的实现 多进程()/多线程(threading)将程序的运行和IO操作分配给独立的进程来完成,这样各个进程之间相互独立互不影响。该方法的缺点是:进程的创建和运行是昂贵的(独立的内存空间和资源);且如各个进程执行的任务不独立,还需要构建进程间的通信。
loop style方法(select/poll)select/poll loop通过循环loop地执行或系统调用,侦听指定IO(file descriptor包括socket)的状态变化,直到满足一定的条件(ready to read/write/error)或达到一定的时间(timeout expires)或获得指定的signal;然后根据select或poll的返回值,再次通过loop判断各个IO的状态,并采取对应的操作(read/write)。
该方法相比较多进程方法,可以以单进程实现多个IO的异步执行。但方法的缺点包括:
They both handle file descriptors in a linear way. The more descriptors you ask them to check, the slower they get. As soon as you go beyond perhaps a hundred file descriptors or so - of course depending on your CPU and hardware - you will start noticing that the mere waiting for file descriptor activity and the following checking which file descriptor that it was, takes a significant time and becomes a bottle neck.
由于select使用bitmask保存要侦听的file descriptor因此需要注意FD_SETSIZE的大小(不同的OS可能不同)。
另外select和poll方法2者的比较参看:, 。
多进程方法 和 select方法 实现并发响应的代码参看:
poll实现并发响应的代码参看:
event-basedevent-based的方法不同于select/pool的event loop方法,它通过为希望侦听的IO(file descriptor)的指定event(或指定timeout)添加响应的callback function,这样当event产生或timeout时间到了,即会自动执行callback函数。
类似的方法有:(Linux Kernel after 2.5.44), kqueue(FreeBSD/NetBSD/OpenBSD/Darwin), /dev/poll(Solaris/HPUX), pollset(AIX), Event Completion(Solaris 10), I/O Completion Ports(Windows)等。
开发中可以使用各OS提供的API,如epoll。或使用一些event-based实现的库:libev和libevent。它们可用于编写可移植的event-based applications。例如libevent支持多种方法:/dev/poll, kqueue(2), select(2), poll(2), epoll(4) and Solaris's event ports.
epoll实现并发响应的代码参看:
libevent库实现高并发socket server参看:
异步IO的应用:异步IO/non-blocking非阻塞IO主要应用于高并发的IO请求,如client/server模式下,server要求对高并发的多 client进行快速响应。已经使用的:http server, database server, cache server等
比较经典的例子即:
Apache HTTP Server是process-based(forking or threaded),它使用loop style的select方法()。Nginx和Lighttpd等轻量级的http server使用了event-based的异步模式,如两者都使用了epoll方法()。 Apache遇到高并发请求,一方面需要创建大量的进程/线程耗费CPU时间,另一方面对每一个select的loop也是非常耗时的;而Nginx /Lighttpd等的epoll基于事件模型,单个请求不需要一个进程/线程陪伴请求整个生命期,抛弃了client请求与进程之间的一对一关系,大量 请求被os接管处理,而连接所耗资源相对较低,所以处理几万个连接是没有问题的。因此后者在高并发方面效果更好,具体比较
另外Memcached等也采用了epoll的网络IO模型。
因此,如果编写的server需要满足高并发请求建议使用event-based的IO模型,使用epoll或libevent库。
参考