文章目录
- 阻塞IO
- 非阻塞IO
- 信号驱动
- 异步IO
- 多路转接(核心终点)
实际上 IO = “等” + 拷贝
等什么呢? -----> 等待的是内核将数据准备好。
拷贝-------> 数据从内核考到用户
IO话题: 无非就是 1 , 改变等的方式 2 , 减少等的比重。
阻塞IO
当内核没有将数据准备好的时候, 系统调用会一直阻塞。 (所有的套接字, 默认都是阻塞)
非阻塞IO
非阻塞IO: 如果内核还未将数据准备好, 系统调用仍然会直接返回, 并且返回EWOULDBLOCK错误码,
非阻塞IO往往需要程序员循环的方式反复尝试读写文件描述符, 这个过程称为轮询, 对CPU来说是低效的。
并且,在非阻塞的情况下, 出错 和 数据未就绪都是以 返回错误的形式。
那如何区分 真正的错误 和 未就绪的情况的呢? ———> 数据未就绪的情况 ----errno ——–> EAGAIN ==11
一个文件描述符fd默认是阻塞IO,如何设置未非阻塞呢?
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
using namespace std;
void SetNoBlock(int fd)
{
int fl = fcntl(fd, F_GETFL); //获得这个文件描述符相关属性f1
if (fl < 0)
{
perror("fcntl");
return;
}
fcntl(fd, F_SETFL, fl | O_NONBLOCK); //将非阻塞设置进该文件描述符fd
}
int main()
{
SetNoBlock(0);
while (1)
{
char buf[1024] = { 0 };
ssize_t read_size = read(0, buf, sizeof(buf) - 1);
if (read_size < 0)
{
cout << "未读到内容" << endl;
sleep(2);
continue;
}
cout << "读到的内容为 : " << buf << endl;
}
return 0;
}
运行结果:
信号驱动
内核将数据准备好以后,通过信号SIGIO信号去通知应用进程。
然后应用进程去调用接口去IO。
异步IO
当应用进程IO的时候, 内核完成了 等 + 拷贝 之后通知应用进程。
信号驱动和异步IO的区别:
内核在数据拷贝完成时, 通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据),
也就是说信号驱动是告诉进程什么时候可以进行IO, 而异步IO是告诉进程什么时候IO(等 + 拷贝都)完成了。
同步通信和异步通信:
同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回. 但是一旦调用返回,就得到返回值了
异步相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果;
当一个异步过程调用发出后,调用者不会立刻得到结果; 而是在调用发出后,被调用者通过状态、通知来通知调用
者,或通过回调函数处理这个调用.
多路转接(核心终点)
可以同时等待多个文件描述符。
在后面的博客分别详细解释select, poll, epoll。