Chinaunix

标题: 关于linux下的异步io,有几个疑问 [打印本页]

作者: ydfgic    时间: 2011-01-25 14:58
标题: 关于linux下的异步io,有几个疑问
n年前还是windows程序员的时候,觉得那本《windows核心编程》是神书,看了一遍一遍的。
特别是后面的多线程部分,异步io,完成端口,觉得很强大。
后来转linux了,也习惯了linux的异步模式。但是心里总是有个疙瘩,那就是没有 完成端口 这样好用的异步调用。
由于两个系统的架构问题,这个确实是linux的一个软肋。
知道 aio 这东西,这里有很不错的文章
http://www.ibm.com/developerworks/cn/linux/l-async/
心想总算linux有补上这个缺憾了。
查了查网上的资料(实在是少)
有几个疑问:

1:aio 对 socket 的支持是不是不完善,或者说有bug?
网上有这样的问题: http://goo.gl/AeZTc

2. 异步线程是内核线程吗?内核自己维护一个线程池?

有没有哪位兄台,有这方面的经验?
作者: ydfgic    时间: 2011-01-25 15:21
晕,论坛里的aio问题还那么多,google上都没有这里多

第二个问题,这里有答案 :http://bbs.chinaunix.net/thread-1705934-1-1.html

是普通的pthread_create线程。

问题真是多啊aio,还是不用了
作者: erlangs    时间: 2011-01-25 15:27
对于linux来说,一切皆为进程
linux下的socket IO复用可以说比windows强多了
{:3_185:}
作者: ydfgic    时间: 2011-01-25 16:29
第一个问题:这里有精彩的回答
现在的 2.6 kernel 只支持文件系统 aio,socket 的 aio 操作都是 libc 用额外的用户线程模拟的。问题是它模拟的也太次了,不说效率怎样,连行为都没模拟正确。

例如:在对一个 socket aio_read 以后进行 aio_write,除非 aio_read 成功,否则后续的 aio_write 都将被阻塞。真正由内核实现的 socket aio 机制(如 freebsd 或 windows)都没有这个问题。

aio 还带阻塞的,这实在太新鲜了,俺实在无语,过来发发牢骚~~





1. aio api 是 posix 标准,我至今在 posix 标准里还没发现没用的东西,相反 posix 里缺的东西倒是不少。posix 之于操作系统就像 libc 之于 C 程序设计语言一样,都是一个最小最起码的功能集合,好像只有嫌它不够的,没见过嫌太多的。

2. AIO 配合每活动连接一线程的模型是目前已知最高效的 IO 模型了。很多 server 都是使用这种模型完成高并发伺服的。Windows、freebsd、solaris、hp-ux 和 IBM AIX 等操作系统都能很好的支持 AIO,它有没有用应该很明显了吧?

3. 有需求才有产品这个概念当然是对的,但是一来基于前两条应该可以证明 AIO 机制有足够的需求,二来操作系统不同于普通的,面向应用的产品。它是人机交互的界面和所有其他产品的基础支撑平台。作为工作的基础,人们对一个现代通用操作系统最少应当提供哪些服务都是有明确标准的。

如果这样还没说清楚。可以回顾一下几年前的线程支持。在 linux 2.2 的年代,也有很多人说线程是没用的东西,需要的话多 fork 几个进程不就完了。但是今天绝大部分职业程序员都会使用线程了,linux 2.6 经过了从 kernel 2.4 的艰难过度(2.4 只支持轻量级进程的概念,而且不支持命名互斥量等同步机制),也终于比较好的支持了线程。

但是在 2.4 的年代,Windows、FreeBSD 等等各家操作系统也都先一步完成的对线程的良好支持。我感觉现在 AIO 就是当年线程的一个相似轮回。当年 linux 从 2.2 的不支持线程到 2.4 的支持轻量级进程还是因为 IBM 支援了大量商业 unix 代码给了 linux 做参考设计才完成的,为此 IBM 被 SCO 起诉,好像还赔了一大笔钱才了事。

今天随着 Solaris、FreeBSD 等越来越多开源 OS 的出现,以及 Linux 开发社区本身的实力增长,这个过度应该比当初要容易多了,没想到 linux 还是比其他 OS 慢了半拍,故有此一叹。

作者: ydfgic    时间: 2011-01-25 16:57
有点失望,这里有个网页:
http://davmac.org/davpage/linux/async-io.html
标题是:
Asynchronous I/O on linux
or: Welcome to hell.

相当醒目。
同时看到stackoverflow 对 aio的抱怨也不是一点半点
作者: rain_fish    时间: 2011-01-25 20:56
epoll
作者: ydfgic    时间: 2011-08-05 14:17
今天查异步io的资料想不到又找到自己以前发的帖子了,看来我没什么进步啊
作者: Missex    时间: 2011-08-05 14:56
我用过用syscall导出的那几个接口,  用起来也很不爽
1. "好像"只支持特定的文件系统
2. 内存什么的还得对齐
3. 和epoll配合使用还要用个eventfd做桥梁, 不(过也好, 方便统一处理了)
4. 即便对于文件系统,有的时候也不是真正异步的,阻塞在io_submit()而不是io_getevents()
作者: cjaizss    时间: 2011-08-05 15:14
I/O模型那么多呢,干嘛在一棵树上吊死,想不通
作者: ydfgic    时间: 2011-08-05 15:50
回复 9# cjaizss


    还不是为了追求那么点效率,现在系统想用直接io代替buffer io,但是直接io又是阻塞的要等磁盘写完才返回,不能有效的减少用户的时间。所以想到了aio + 直接io。
但是libc的aio又是那么的蛋疼,查了下,有个libaio库不错,看看怎么去用
作者: yulihua49    时间: 2011-08-05 15:51
本帖最后由 yulihua49 于 2011-08-05 15:53 编辑
n年前还是windows程序员的时候,觉得那本《windows核心编程》是神书,看了一遍一遍的。
特别是后面的多线程 ...
ydfgic 发表于 2011-01-25 14:58



    epoll代替CPIO!
作者: yulihua49    时间: 2011-08-05 15:56
第一个问题:这里有精彩的回答
ydfgic 发表于 2011-01-25 16:29



    epoll+线程池+连接池,LINUX很强大。比其他系统超前N拍!!!
作者: cjaizss    时间: 2011-08-05 16:05
回复  cjaizss


    还不是为了追求那么点效率,现在系统想用直接io代替buffer io,但是直接io又是阻塞 ...
ydfgic 发表于 2011-08-05 15:50



    别的模型效率也很高
作者: ydfgic    时间: 2011-08-05 16:11
郁闷,怎么老是说我帖子里有非法的文字,不让发
作者: ydfgic    时间: 2011-08-05 16:17
回复8楼:
你说的是内核支持的异步io,我正在看的libaio库好像就是对这些系统调用的封装。
好像ngix也是用这个异步io,有文章说这个实现非常好。同样的oracle好像也是用这个异步io。
好像是挺麻烦的使用上,但是为了提高效率这点还是值得。内存对齐好像是为了用直接io。
不过就像你说的,有的文件系统不支持这套api怎么办,用的时候还得查查。
作者: ydfgic    时间: 2011-08-05 16:20
epoll+线程池+连接池,LINUX很强大。比其他系统超前N拍!!!
yulihua49 发表于 2011-08-05 15:56


你说的是网络模型,确实epoll+线程池非常强大。但是epoll用在文件io上,我看到这类用法好少,不知道是不是也是对一系列的fd进行监控,然后调用read,write。真的很少看到这类用法,所以我这里想知道的是异步io,在文件io上的用法
作者: ydfgic    时间: 2011-08-05 16:23
别的模型效率也很高
cjaizss 发表于 2011-08-05 16:05



工作中想了解下各个模型的效率差异,要不我也不会纠结这个了。现在在准备写个测试程序做做测试,看看各种模型的差异在哪里。呵呵
作者: Missex    时间: 2011-08-05 17:07
郁闷,怎么老是说我帖子里有非法的文字,不让发
ydfgic 发表于 2011-08-05 16:11



    我的ID有问题
作者: Missex    时间: 2011-08-05 17:10
回复8楼:
你说的是内核支持的异步io,我正在看的libaio库好像就是对这些系统调用的封装。
好像ngix也是用 ...
ydfgic 发表于 2011-08-05 16:17


nginx用的是syscall封装,
oracle可能自己修改过内核
这个数据对齐在实际使用中很不方便
作者: yulihua49    时间: 2011-08-05 17:25
你说的是网络模型,确实epoll+线程池非常强大。但是epoll用在文件io上,我看到这类用法好少,不知道是不 ...
ydfgic 发表于 2011-08-05 16:20



    可以。
作者: 鸡丝拌面    时间: 2011-08-06 15:17
epoll是同步,iocp才是异步。如果讲效率,那么都不错。
作者: shanehan    时间: 2011-08-08 15:09
epoll是同步,iocp才是异步。如果讲效率,那么都不错。
鸡丝拌面 发表于 2011-08-06 15:17


epoll应该算是数据同步吧!
作者: yulihua49    时间: 2011-08-08 15:16
epoll是同步,iocp才是异步。如果讲效率,那么都不错。
鸡丝拌面 发表于 2011-08-06 15:17



    什么是异步?epoll为什么是同步?
作者: 鸡丝拌面    时间: 2011-08-08 16:02
什么是异步?epoll为什么是同步?
yulihua49 发表于 2011-08-08 15:16



    你说啥是异步?我认为异步是io任务完成后再通知,而epoll是告诉你可以read或write了。
作者: shanehan    时间: 2011-08-08 17:19
从概念上epoll算是异步,但没有IOCP的完成回调,但实现这种完成回调机制应该是要付出一些代价的
作者: Missex    时间: 2011-08-08 18:09
本帖最后由 Missex 于 2011-08-08 18:29 编辑
你说啥是异步?我认为异步是io任务完成后再通知,而epoll是告诉你可以read或write了。
鸡丝拌面 发表于 2011-08-08 16:02



不错 epoll仅仅是通知机制,  异步机制是, 发起一个读或者写, 然后系统通知你读写的结果,读写了多少, 成功或者失败
作者: yulihua49    时间: 2011-08-09 15:07
本帖最后由 yulihua49 于 2011-08-09 15:18 编辑
不错 epoll仅仅是通知机制,  异步机制是, 发起一个读或者写, 然后系统通知你读写的结果,读写了多少, ...
[url]



      好 像 不 是 这 个 定义。异步操作(区别于异步串行接口之类),指,任务发布了,不等结果。在适当的时候(轮询,或中断,或事件通知),取得结果。
所以,不能说哪个是同步机制,哪个是异步。他们是异步操作的通知工具。

我们把epoll用在异步操作场合:
转发器:
从客户端收到消息,发送给服务器。不知道服务器何时能返回。线程不等待了,交给epoll。这个线程就干别的去了。这就是异步。
等服务器回话了,就会有一个线程处理它,收服务器的消息,返回给客户端。
这种流程不知CPIO如何处理?
作者: 鸡丝拌面    时间: 2011-08-09 15:10
从概念上epoll算是异步,但没有IOCP的完成回调,但实现这种完成回调机制应该是要付出一些代价的
shanehan 发表于 2011-08-08 17:19



    从实现上讲epoll是有aio的特性的,是它挂的fd反过来通知epollfd的。而iocp通过GetQueuedCompletionStatus抱死在那里其实性能也好不到哪里去。同步异步,其实没有必要恰得那么死,win的所谓overlapped io可以通过callback通知(这个算是严格异步),也可关联一个event来等(这个算啥呢,杂种? )。
作者: 鸡丝拌面    时间: 2011-08-09 15:13
好 像 不 是 这 个 定义。异步操作(区别于异步串行接口之类),指,任务发布了,不等结果。在 ...
yulihua49 发表于 2011-08-09 15:07



    你说得其实不差。同步就是收/发一坨xx,然后等同步信号,再收/发另一坨xx;不是这么的就算异步。自从io复用及其进化体出来后,同步异步是你中有我,我中有你了。
作者: yulihua49    时间: 2011-08-09 15:22
本帖最后由 yulihua49 于 2011-08-09 15:47 编辑
从概念上epoll算是异步,但没有IOCP的完成回调,但实现这种完成回调机制应该是要付出一些代价的
shanehan 发表于 2011-08-08 17:19


不能完成回调啊。线程抱死了!就是应该等通知再找一个线程callback.

10000个客户端连接,16个工作线程,160个服务器连接。线程从不抱死在任务上。每秒可转发60000个客户请求,120000次递送。线程抱死了,怎么玩?


这样看,CPIO是同步的,要等完成嘛。epoll是真正异步的。

走题了。楼主问读写文件。大多数读写文件用不着这个。
作者: jiayanfu    时间: 2011-08-09 15:52
帮楼主顶起来。。。。{:2_176:}
作者: 鸡丝拌面    时间: 2011-08-09 16:41
不能完成回调啊。线程抱死了!就是应该等通知再找一个线程callback.

10000个客户端连接,16个工作线 ...
yulihua49 发表于 2011-08-09 15:22



    无论等完成还是等可用都会遇到抱死问题,所以有timeout
作者: yulihua49    时间: 2011-08-09 16:48
本帖最后由 yulihua49 于 2011-08-09 17:20 编辑
无论等完成还是等可用都会遇到抱死问题,所以有timeout 。
鸡丝拌面 发表于 2011-08-09 16:41

等可用不会遇到抱死问题吧?除非是根本就没有激活的任务了,那叫空闲,不叫抱死。

以上边的例子,在一个服务器响应时间内,要完成数十的数据交换。
抱死的话,每个连接一个线程还凑合,你仔细分析一下我前边的帖子里的参数。这是实际的应用。
每连接一个线程,TPC,性能很差的。不可能玩10000个客户端。
timeout也是因为不希望任务在epoll队列里无穷的等待。

在线程池模式里,
线程数与核数基本相等,太多的线程性能退化。这么少的线程,抱死了就别干了。
这个程序为防抱死,花了很多功夫的,等待取连接池都不抱死,把任务丢到一个队列里等待调度。


如果是TPC,那个转发器,要产生10000个线程,160个活动的。性能会很差的,大部分开销是操作系统的线程调度了。

它是一个典型的异步应用,我正发愁如何移植到WINDOWS上,IOCP能胜任吗?
作者: yulihua49    时间: 2011-08-10 10:49
等可用不会遇到抱死问题吧?除非是根本就没有激活的任务了,那叫空闲,不叫抱死。

以上边的例子,在一 ...
yulihua49 发表于 2011-08-09 16:48



    想明白了。IOCP完成的不一定就是这个线程刚放进去的任务,可能是任何一个任务,那就没什么问题。可以算是异步的。
作者: shanehan    时间: 2011-08-10 13:52
IOCP的实现不算很了解,不过效率应该还是不错的,复杂的设计很符合MS的风格
作者: herocsz    时间: 2013-05-10 15:41
rain_fish 发表于 2011-01-25 20:56
epoll


这么好的技术没人重视?
作者: yulihua49    时间: 2013-05-10 15:57
本帖最后由 yulihua49 于 2013-05-10 15:59 编辑
ydfgic 发表于 2011-01-25 14:58
n年前还是windows程序员的时候,觉得那本《windows核心编程》是神书,看了一遍一遍的。
特别是后面的多线程 ...

挖坟了。
作者: yulihua49    时间: 2015-01-20 16:33
本帖最后由 yulihua49 于 2015-02-27 10:11 编辑
ydfgic 发表于 2011-01-25 14:58
n年前还是windows程序员的时候,觉得那本《windows核心编程》是神书,看了一遍一遍的。
特别是后面的多线程 ...

IOCP  == epoll + aio + eventfd
fiber   == ucontext.
都有对应的。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2