1、非阻塞I/O。非阻塞I/O:若想网络编程时调用I/O函数不想让程序阻塞,需要使用I/O复用技术,一个方法是poll(轮询)
所谓轮询就是执行函数时,如果内核不能立即对应用的函数进行响应时,就返回给应用一个错误,而应用不停的循环调用该函数,直到有响应。如果不使用轮询,则在内核对函数响应期间,应用只能阻塞在该函数这,而不能往下执行。
2、信号驱动I/O模型。当应用进行互动时,归根到底都是阻塞在内核处,使得程序不能往下执行。有个方法是内核准备好让用户调用数据时,发给程序一个信号,用户这时就使用I/O函数来调用数据。这样就不至于提前调用I/O函数导致早早的便阻塞了。而用户需要做的仅仅是在最前面定义一个信号处理程序。
3、异步I/O模型。和上一个模型很相似,区别是上个模型作用是由内核告诉我们何时可以使用I/O操作。而异步I/O模型是告诉我们I/O操作何时完成。其中一个函数为aio_read函数。给内核传递描述符、缓冲区指针、缓冲区大小和文件偏移,并让内核在read操作完成时告诉我们。该函数是非阻塞的,调用后立即返回,而内核依然在执行该函数。
4、I/O复用。调用select或poll函数,使得系统调用阻塞在这两个函数,而不是阻塞在I/O操作函数。
select函数:允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或经历一段指定时间后才唤醒它。当指定的时间为0时,检查描述符后立即返回,这时称为轮询。
根据我的理解,select函数可以将多个描述符按照符合要求的编号进行筛选,比如,如果查询哪些描述符现在可读,就将该描述符所在的描述符集和限定的最大描述符查询编号作为参数传入select函数,select会进行筛选,结束后描述符集里的描述符就只剩下可读的描述符了。
poll函数:第一个参数为pollfd结构体。pollfd结构体传入参数为描述符号,想要测试该端口号的功能以及返回的状态。例如,想要测试一个端口是否可写,就将端口号、(POLLOUT)以及一个变量分别作为1、2、3形参传入函数,如果变量值变为POLLOUT,则说明该端口可写。第二个参数为pollfd结构体数组元素的个数。第三个是poll函数等待时间。
可用来设置描述符的I/O模式的函数:fcntl。它的三个参数分别为端口号;F_GETFL或F_SETFL,作用是用来获得套接字类型或者设置套接字类型;设置参数,可设套接字为非阻塞型I/O或者信号驱动型I/O。