IO的方式有阻塞IO,非阻塞IO,IO复用,信号驱动,异步IO等。
1.阻塞IO
阻塞IO是最通用的IO类型,使用这种模型进行数据接收时,在数据没有到之前程序会一直等待。
2.非阻塞IO
当把套接字设置为非阻塞的IO,则对每次请求,内核都不会阻塞,会立即返回; 当没有数据的时候,会返回一个错误。
3.IO复用
使用IO复用模型可以在等待的时候加入超时时间,当超时时间没有到达的时候与阻塞的情况一致,而当超时时间到达仍没有数据接收到,系统会返回,不再等待。
4.信号驱动IO模型
信号驱动的IO在进程开始时注册一个信号处理的回调函数,进程继续执行, 当数据到来时,使用信号通知注册的信号处理函数。
5.异步IO模型
异步IO与信号驱动IO相似,其区别在于信号驱动IO当数据到来时,使用信号通知注册的信号处理函数,而异步IO则在数据复制完成时才发送信号通知注册的信号处理函数。
二. select()和pselect()函数
函数select()和pselect()用于IO复用,它们监视多个文件描述符的集合,判断是否有符合条件的事件发生。
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
nfds: 一个整型变量,它比所有文件描述符集合中的文件描述符的最大值大1,使用select时必须计算最大值的文件描述的值,将值通过nfds传入。
readfds: 这个文件描述符集合监视文件集中的任何文件是否有数据可读,当select()函数返回时,readfds将清除其中不可读的文件描述符,只留下可读的文件描述符。
writefds:这个文件描述符集合监视文件集合中的任何文件是否有数据可写,当select()函数返回时,writefds将清除其中的不可写的文件描述符。
exceptfds: 监视文件集中的任何文件是否发生错误。
timeout: 设置在select()所监视的文件集合中的事件没有发生时,最长的等待时间。 当超过此时间时,函数会返回。 当超时时间为NULL时,表示阻塞操作,会一直等待,直到某个监视的文件集中的某个文件描述符符合返回条件。 当timeout值为0时,select会立即返回。
timeout类型是如下结构
struct timeval
{
time_t tv_sec; //秒
long tv_usec; //微秒
};
有4个宏可以操作文件描述符的集合
FD_ZERO(): 清理文件描述符集合
FD_SET(): 向某个文件描述符集合中加入文件描述符
FD_CLR(): 从某个文件描述符的集合中取出某个文件描述符
FD_ISSET(): 测试某个文件描述符是否某个集合中的一元。