Chinaunix首页 | 论坛 | 博客
  • 博客访问: 121445
  • 博文数量: 41
  • 博客积分: 2564
  • 博客等级: 少校
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-20 19:17
文章分类

全部博文(41)

文章存档

2009年(41)

我的朋友

分类: LINUX

2009-04-14 14:20:39

在网络编程中I/O复用非常有用,具体的原因就不用说了,相信用过的人都有体会~


1、I/O模型

在Unix中,有5中基本的IO模型,它们是:

·blocking I/O

最普通的I/O模型,也是默认的I/O模型。它会一直阻塞调用者直到读/写成功、被信号中断或错误发生。

·nonblocking I/O

通过调用一些函数,可以将blocking I/O设置为nonblocking模式。nonblocking模式下,进行I/O操作不会被阻塞,无论成功与否都会返回,返回值和errno表明了操作状态。

·I/O multiplexing (select/poll)

对于同时处理多个I/O的进程(线程)来说,这很有用。它相当于同时“监视”多个I/O,在满足一定的条件后返回,向调用者“反馈”情况。

·signal driven I/O (SIGIO)

有事件发生时,同时信号的方式通知“对此感兴趣”的对象。

·asynchronous I/O

执行I/O操作后立即返回,但不代表实际的操作已经进行,什么时候执行实际操作由底层决定。实际操作执行完毕后底层会通知相应的对象。

前面4种模型和最后一种的一个显著区别是:

前面4种模型不会主动把数据从内核复制到用户进程,只有当用户进程使用系统调用读取数据时才会复制过来;而使用异步I/O时,当底层通知调用者操作完成时,已经将数据从内核复制到了相应的用户进程。

2、select

提到unix下的I/O复用,就不得不提select。虽然还有一个poll,但是select的使用远远要比poll广泛,POSIX对select的支持也要多于poll。select有一个更为强大的版本pselect,而poll则没有(后面出现了epoll,主要是为了网络而设计的)。

使用select时,需要注意几点:

·是它的3个fd_set是value-resule类型,调用select的时候,代表的是感兴趣的事件,而返回  的时候被修改为已经发生的事件。使用select常犯的一个错误就是,select返回后再次调用没有  重新设置3个fd_set。

·timeval指针参数是为了实现超时而用的,它可以为NULL、0(tv_sec和tv_usec为0)和大于  0。为NULL代表一直阻塞知道有事件发生,0表示无论有没有事件发生都立即返回,大于0表示阻塞  的最大时间。

·timeval指针参数使用const限制符,也就是说它返回的时候不会向其他一些具有定时功能的函数  一样,将其修改为“剩下的时间”。

·操作fd_set用FD_ZERO、FD_SET、FD_CLR和FD_ISSET宏。


2.1 什么时候socket为“可读”

·socket接收缓存中的字节数大于socket接收缓存的“low-water”值(对于TCP和UDP默认值一般  为1,可通过SO_RCVLOWAT选项进行设置)。

·读端被关闭,如收到了FIN包。此时read将立即返回,返回值为0,表示遇到EOF。

·socket是监听端口,且到该端口连接完成的端口数不为0,即accept可以立即返回。

·socket有错误发生,此时read将立即返回,返回值为-1,errno为发生的错误。错误还可以通过  getsockopt采用SO_ERROR获得。

2.2 什么时候socket为“可写”

·socket发送缓冲中可用空间大于socket发送缓存的“low-water”值(对于TCP和UDP默认值一般  为2048,可通过SO_SNDLOWAT选项进行设置)。

·写端关闭(比如收到RST),此时write会返回EPIPE。

·socket以nonblocking方式使用的connect连接成功或失败。

·socket有错误发生,“可读”。

由上面可知,当一个socket发生错误时,select认为是可读写的。

2.3 增强版select---pselect

从表面上看,有2个不同:timeval结构变成timespec结构;增加了一个参数const sigset_t *sigmask。

(未完待续)

阅读(1106) | 评论(0) | 转发(0) |
0

上一篇:Unix网络编程指南

下一篇:TCP socket选项

给主人留下些什么吧!~~