Windows与类Unix平台上各种IO模型工作模式的讨论?
时间:2008-05-13 15:24:43
来源:论坛整理 作者: 编辑:chinaitzhe
并对Windows上的各种IO模型都编写了相应的事件处理模块,
具体请到我的博客去看看:http://blog.csdn.net/ngwsx/。
现在有个疑问,就是具体各种IO模型的工作模式是什么?
这里说的工作模式有两种:
Level Triggered (LT)(条件触发)
Edge Triggered (ET)(边缘触发)
Level Triggered 工作模式:
通过调用某种IO方法,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。
假如你不对该描述符作任何操作,当你再次调用该IO方法,内核还是会继续通知你的。
Edge Triggered 工作模式:
当描述符从未就绪变为就绪时,内核通过你调用IO方法时告诉你。然后它会假设你知道文件描述符已经就绪,
并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了
(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。
但是请注重,假如一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once)。
我想知道的是以下这些IO模型的工作模式是上面这两种的那一种,大家来讨论讨论吧。
Windows平台:
select
WSAAsyncSelect
WSAEventSelect
OverlappedIO
IO Completion Port
WSAPoll
类Unix平台:
select
poll
devpoll
epoll
kqueue
aio
eventport
rtsig
现在ngwsx是这样的工作模式:
(1)主线程通过调用select/WSAAsyncSelect/WSAEventSelect/OverlappedIO/IOCP/WSAPoll
这些函数来检测IO事件是否就绪或IO操作是否已经完成;假如已经预备好,
就投递相应的事件到内部一个队列中。
(2)多个工作线程同时从队列中取出事件并处理它。
因为这种工作模式,ngwsx要确保不能投递重复的事件到队列中,
所以需要了解各种IO模型的工作模式。
网友回复:谁来说说吗?
网友回复:怎么没人发言呀,我发错地方吗?
网友回复:跨平台的移植,一般都不敢随便说话的,何况还涉及到IO操作...
网友回复:我来说话,用SELECT好了,所有平台都有
(1)主线程通过调用select/WSAAsyncSelect/WSAEventSelect/OverlappedIO/IOCP/WSAPoll
这些函数来检测IO事件是否就绪或IO操作是否已经完成;假如已经预备好,
就投递相应的事件到内部一个队列中。
(2)多个工作线程同时从队列中取出事件并处理它。
你这个方法很有创意,效率如何
网友回复:这个不是我的创意,官方nginx就有的,不过它现在还不支持这种工作模式,
现在nginx是一个主进程多个工作进程这种模式,
假如比较两者的效率,那肯定是主线程多工作线程这种模式。
里面实现的事件队列是这样子的:
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ /* 首先ngx_event_t结构的定义是:*/ typedef struct ngx_event_s ngx_event_t; struct ngx_event_s { ... /* 其它结构字段 */ ngx_event_t *next; ngx_event_t **prev; }; /* 这个互斥体用于保护事件队列 */ ngx_mutex_t *ngx_posted_events_mutex; /* * ngx_posted_events事件队列,官方nginx还有一个事件队列ngx_posted_accept_events。 */ ngx_thread_volatile ngx_event_t *ngx_posted_events; /* 事件入队 */ /* * ev参数传入检测到的IO事件(用ngx_event_t结构变量来保存)的指针, * queue参数传入ngx_posted_events的指针,也就是ngx_event_t二级指针。 */ #define ngx_locked_post_event(ev, queue) \ \ if ((ev)->prev == NULL) { \ (ev)->next = (ngx_event_t *) *(queue); \ (ev)->prev = (ngx_event_t **) (queue); \ *(queue) = ev; \ \ if ((ev)->next) { \ (ev)->next->prev = &(ev)->next; \ } \ \ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, (ev)->log, 0, \ "post event %p", ev); \ \ } else { \ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, (ev)->log, 0, \ "update posted event %p", ev); \ } #define ngx_post_event(ev, queue) \ \ ngx_mutex_lock(ngx_posted_events_mutex); \ ngx_locked_post_event(ev, queue); \ ngx_mutex_unlock(ngx_posted_events_mutex); /* 事件出队 */ #define ngx_delete_posted_event(ev) \ \ *(ev)->prev = (ev)->next; \ \ if ((ev)->next) { \ (ev)->next->prev = (ev)->prev; \ } \ \ (ev)->prev = NULL; \ \ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, (ev)->log, 0, \ "delete posted event %p", ev);
网友回复:这个还真不好说
这几天看开源的web server
感觉就是,linux 2.6以前的轻量级一般都选择poll/select,
性能高一点的都选择kqueue,现在2.6以后的一般都选择epoll
poll/select的缺点都是轮询,必须遍历所有点fd, 而且select监听fd还是有数量限制的
epoll是2.6以后的API,据说性能比poll高的相当多,
网上有这几种复用方式的评估结果,你可以参考一下
网友回复:ET,LT是epoll里的
似乎ET的性能更好,这个网上也有评估结果供参考
网友回复:你说的这些我都有所了解,
EPOLL的工作模式ET与LT我也知道,
我就是通过EPOLL才知道这两种工作模式的,
我认为其它的IO模型也应该是具有这两种工作模式的一种或二种的?
就拿select来说吧,它应该是LT这种工作模式的,
当调用select检测到一个可读套接字描述符时,
然后假如不调用recv去读,
当下次调用select还是会检测到相同的可读套接字描述符。
poll也应该是LT工作模式,
Windows的IO完成端口应该是ET工作模式的。
其它的就不太确定。
虽然可以通过编写程序来了解所有这些IO模型的工作模式
但在这里希望对这些IO模型有过相关使用经验的朋友来说说。
网友回复:
你这样理解也是可以的,但是select/poll, 就算是和epoll中的LT比还是有差距的
二者并不一样
网友回复:你是说具体实现吗?
那肯定不一样!
网友回复:没人?
网友回复:up
关键字:Windows,Unix,平台,各种,IO,
上一篇:昨天上午的面试题,大家来做做吧。
下一篇:下面没有链接了











文章评论
共有 0 位网友发表了评论 此处只显示部分留言 点击查看完整评论页面