UNIX下的5种IO模型
a.阻塞式
b.非阻塞式IO
c.I/O复用
d.信号驱动IO
e.异步IO
阻塞式I/O
默认情况下所有的套接字都是阻塞的
非阻塞式IO
I/O复用模型
使得可以不阻塞在单个的系统调用上,转而阻塞在epoll或者poll上
信号驱动式I/O
先开启套接字的信号驱动式IO功能,通过sigaction设置处理行为,当行为可以发生时将收到信号
异步I/O模型
告诉内核我们启动了某个操作,当内核完成了该操作时将通知我们,与上文所述的信号驱动式I/O的区别在于:信号驱动告知的是我们何时可以开启某个操作,而异步则是告知我们何时操作完成了
select函数
功能:允许进程指示内核等待多个关心的事件,只有一个或多个事件真实被发生或者超时才会通知进程
原型:
extern int select (int __nfds, fd_set *__restrict __readfds,
fd_set *__restrict __writefds,
fd_set *__restrict __exceptfds,
struct timeval *__restrict __timeout);
timeout指定最多等待的超时时间,readfds,writefds,errfds指定我们关心的读写和错误事件
fd_set的底层实现是整数数组所有的操作都被隐匿在如下的宏中
如果对某个事件组不感兴趣,那么直接将其fds指针置空,如果都为空那么将获得一个比sleep更加准确的睡眠函数,(sleep以秒计算)
nfds是最大的感兴趣文件描述符+1(0-最大描述符共+1个)
函数返回后,使用FD_ISSET轮询的测试即可,需要注意的是描述符中任何未发生时间的FD将被重新设置为0,因此需要再次的用FD_SET设置事件
描述符准备就绪的具体条件
对于读就绪
a.套接字接收缓冲区大于等于接收缓冲区低水位标志
b.该连接半关闭(收到对端的FIN标志位)
c.监听套接字上的已完成连接数(ESTABLISH)不为0
d.有一个套接字的错误待处理
对于写就绪
a.套接字发送缓冲区可用字符数大于等于发送缓冲区低水位标志
b.连接的写对端关闭,对这样的对端写将产生SIGPIPE信号
c.非阻塞的connect建立连接,或者connect已经失败
d.套接字上有错误
extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
__fortified_attr_access (__write_only__, 1, 2);
shutdown函数
原型:
extern int shutdown (int __fd, int __how) __THROW;
功能:关闭本端链接
close有两个局限性,第一是只有在文件计数为0的时候才真正的关闭socket
第二是close如果满足关闭条件会关闭读写两个端
shutdown有效的避免了这两种情况,第一,shutdown无论如何都会发送FIN,第二shutdown可以指定关闭读端还是关闭写端
poll函数
原型:
extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
__fortified_attr_access (__write_only__, 1, 2);
struct pollfd
{
int fd; /* File descriptor to poll. */
short int events; /* Types of events poller cares about. */
short int revents; /* Types of events that actually occurred. */
};
功能:IO多路复用