OSX/iOS中多路I/O复用总结
来源:互联网 发布:三菱3u编程口接线图 编辑:程序博客网 时间:2024/06/05 09:10
OSX/iOS中多路I/O复用总结
在OSX/iOS中IO多路复用通常会选择select和kqueue,最近在尝试优化socket改进通信效率,所以总结一下两种模型的用法。
select
select是socket编程中非常重要的一个函数,并且也是兼容性最好的一种模型,在unix、linux、windows都有对应的实现,其函数原型是:
1234567
int select( int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, const struct timeval* timeout);
nfds最大的文件描述符加1;
readfds:用于检查可读性的描述符集合,同时也是可读描述符的结果返回;
writefds:用于检查可写性的描述符集合,同时也是可写描述符的结果返回;
errorfds:用于检查异常的描述符集合,同时也是异常描述符的结果返回;
timeout:一个指向timeval结构的指针,用于决定select等待I/O的最长时间,它可以使select处于三种状态:
(1)第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;
(2)第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;
(3)第三,timeout的值大于0,这就是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,>返回值同上述。
函数返回值:
负值:select错误
正值:某些文件可读写或出错
零值:等待超时,没有可读写或错误的文件
kqueue
kqueue是FreeBSD上的一种的多路复用机制,所以刚好能在OSX/iOS中使用。它是针对传统的select处理大量的文件描述符性能较低效而开发出来的。注册一批描述符>到kqueue以后,当其中的描述符状态发生变化时,kqueue将一次性通知应用程序哪些描述符可读、可写或出错了.
kqueue模型最主要的函数就是kevent,它与select类似,提供向内核注册/反注册/修改事件和返回就绪事件或错误事件,函数原型为:
12345678
int kevent( int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout);
kq:由kqueue()返回的一个内核事件队列标识;
changelist:注册/反注册事件的列表;
nchanges:changelist的个数;
eventlist:用于返回有事件发生的列表;
nevents:传入的eventlist的最大长度;
timeout:一个指向timeval结构的指针,指定超时时间;
函数返回值与select类似。
另外比较重要的就是struct kevent这个结构体了,它既是注册、反注册、修改事件的载体,也是事件返回的载体,它的原型为:
12345678
struct kevent { uintptr_t ident; short filter; u_short flags; u_int fflags; intptr_t data; void *udata;};
由于kqueue不仅仅用于socket,还可用于如文件状态、信号、进程等用途,以下仅仅当在网络编程时这些元素的值及含义:
ident:事件的id,实际应用中,一般设置为文件描述符;
filter:指定你希望内核用于ident成员的过滤器,我们可以指定EVFILT_READ(读状态)和EVFILT_READ(写状态);
flags:告诉内核应当对该事件在队列做何处理,我们可以指定EV_ADD(注册)、EV_DELETE(删除)、EV_ENABLE(开启,默认)、EV_DISABLE(停用),当flags用于eventlist返回事件时,可能包含EV_ERROR的掩码表示描述符错误事情;
fflags:用于指定你想让内核使用的特定于过滤器的标志;
data:用于保存任何特定于过滤器的数据,当filter指定为EVFILT_READ或EVFILT_READ时,data表示可读或可写的数据长度,当事件的描述符出错时,data表示错误>代码;
udata:data成员并不由kqueue使用,kqueue会把它的值不加修改地透传,用于类似于上下文。
总结
select的缺点:
(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
(3)select支持的文件描述符数量太小了,默认是1024(不同平台对FD_SETSIZE设定不一样)
(4)select接口使用并不灵活,无法分步提交集合,也无法将提交和查询分步,必须在一次调用中完成
(4)fd_set不能逆向转换为fd,需要再单独维护一份描述符的列表
而kqueue刚好能弥补这些缺陷,但却无法在其它平台使用
关于两种模型的实现示例下载:
SocketServer_select.zip
SocketServer_kqueue.zip
- OSX/iOS中多路I/O复用总结
- I/O复用总结
- Java I/O总结
- I/O读写总结
- I/O问题总结
- Java I/O总结
- java I/O总结
- java I/O总结
- Java I/O 总结
- Java I/O总结
- Java I/O 总结
- Java I/O 总结
- File I/O总结
- Java I/O 总结
- 基础I/O总结
- I/O复用和I/O模型
- I/O复用简述
- I/O复用机制
- VMware View 5.0从菜鸟到高手系列 3 -安装View Composer组件篇
- AndroidManifest 中original-package标签
- Matlab 三维图像绘制(2)——surface property、view、空间圆柱体
- ThreadLocal解析
- JNI添加外部.so到armeabi目录mk方式
- OSX/iOS中多路I/O复用总结
- 宾夕法尼亚立法者推迟线上博彩投票
- xcodebuild 命令 后面加一个 GCC_OPTIMIZATION_LEVEL=0,这样 就可以调试 了 静态库了
- VMware View 5.0从菜鸟到高手系列 4 -虚拟桌面模板篇
- The Failover Transport(失败故障转移传输)
- sql 生成随机数 以及不重复随机数
- ANT教程之八 Ant构建文档
- VMware View 5.0从菜鸟到高手系列 5 -配置View Connection Server篇
- Linux socket编程