PoEdu - Windows阶段班 【Po学校】 Lesson004_003-1 IO操作
-
Windows编程 Lesson004_003-1 IO操作
- 001 什么是Windows的IO:(Input / Output)
- 从编程语言角度来看IO操作有:标C中的printf与scanf就是IO操作、C++中有cout与cint也是IO操作,打开文件等都是IO操作。
- windows平台上的IO有几类:
- 1 操作文件
- 2 外部设备操作,对于所有“设备”的操作,都是IO操作。设备概念:除了内存以外,都可以称之为设备 。
- 常见外部设备有 1硬盘(文件)
- 3 网络通信
- 002 完成端口机制
- 完成端口机制 由来:
- windows是 “多任务,多线程”的操作系统,在多核CPU上,windows操作系统有完善的并行处理机制,通过多核,并行多线程执行程序; 如今计算机的瓶颈,不在是CPU的速度,或内存速度,或内存大小等因素,瓶颈在于“外部设备(硬盘)”之上。IO操作外部设备,特别是硬盘文件的IO操作上,外部设备响应速度跟不上,线程会被挂起;为了避免这种IO操作上的瓶颈,就有了“完成端口机制”。
- 完成端口机制 流程:
- 当有IO请求发起,“完成端口机制”是先接收到请求,不去等待外部设备的IO操作完成,而是直接返回,先去处理其它任务;直到IO操作完成后发起通知,才去处理IO完成后的任务。
- 003 文件内核对象的理解
- IO操作:
- 1 与文件之间的IO操作
- 2 和目录之间的IO操作
- 3 与逻辑磁盘之间的IO操作
- 4 与物理磁盘之间的IO操作
- 5 串口IO操作
- 6 并口IO操作
- 7 邮件槽IO操作 (少见)
- 8 命名管道IO操作
- 9 匿名管道IO操作
- 10 套接字IO操作
- 11 控制台IO操作 (少见)
- 设备的抽象概念:文件、目录、逻辑磁盘、物理磁盘、串口、并口、等,都可以看成”设备“;
- 文件格式
- 二进制文件
- 文本文件
- 目标文件
- 超文本
- ……等等
- 文件内核的由来:
- 文件、目录、逻辑磁盘,本质上是windows为了方便管理,为用户虚拟出来的二进制数据。二进制数据有了一些”文件“的属性后,它就是文件,文件属性设置了属于哪个”目录“,就有了目录;目录建立之初,设置属性属于哪个”逻辑磁盘“,就有了逻辑分区。这一套”文件“管理机制,由windows操作系统来维护管理:”文件内核对象“是最为关键所在。
- 磁盘上的文件,本质上是一段存放在磁盘扇区上的二进制数据,打开了文件,这段”二进制数据“就要加载进内存,那么问题来了:操作系统如何确定”二进制数据“的大小?或者说:从哪里起始,加载进入内存,又在在哪里确定边界?——用C++的面向对象来理解:操作系统可以设计一个专门的类(或结构体),来处理初始化”二进制数据“,使其构造成为文件。实际上windows操作系统上,设计了专门的结构体,来处理文件的初始化。而这些结构体都保存在内核里面,所以“文件类”产生的对象,就是“文件内核对象”。
- 内核当中存在的类或结构体,我们不能直接new出一个对象,windows操作系统提供了系列win32API 来获取文件内核对象。
- 004 所有的设备类型的讲解
- 串口、并口 :两种不同的接口,代表两种不同的通信方式。串口是通过电话线发送型号,单通道;并口是8通道。
- 邮件槽 : 局域网中, 一对多的服务或传输方式。
- 管道 : 命名管道,局域网中一对一的传输方式。匿名管道,主要用于本机之间通信。
- 本机之间为什么还要匿名管道呢?实际上,本机中,进程与进程之间隔离,相对独立,匿名管道就提供了通信传输的渠道。
- 当然也可以采用套接字Socket通信。
- 套接字 Socket: 报文或数据流传输,通过网络。
- 网络社会基于套接字来传输。
- 005 R3层和R0层文件对象的交互
- 文件对象交互流程:
- APP应用程序-->
- "打开并读取磁盘文件xxx.txt" -->
- 调用win32API函数 -->
- 通过R3层检测 -->
- R0层找到文件所在 -->
- 文件内核管理 加载文件到内存 -->
这里会根据文件类型来决定,是否读取文件。 - 构造“文件内核对象” (内核对象代表文件所在空间) -->
-
-
-
-
-
-
-
-
-
- 以“文件内核对象”来做标识标记 ,存放在内存中 -->
此时会有文件的系列信息表生成,把信息表里的部分数据传递出去,内核对象不对暴露出去,只有通过验证过后,才能操作内核对象,内核层才是安全的。- 内存中有了文件内核对象,则返回用户层R3层,通知用户,打开成功 <--||
- 以“文件内核对象”来做标识标记 ,存放在内存中 -->
-
-
-
-
-
-
-
-
-
- 文件打开成功 -->
- 通过R3层,通知API函数 -->
- 返回的是“文件内核对象”的句柄 -->
并不会返回“文件内核对象”本身,因为R0层和R3层是中断的(不在一个位面)。只能是额外的开辟一块区域,R0层把参数传到这块区域后,R3层来读取。R3层能获得的,只是“文件内核对象”的一个编号,这个编号就是“句柄”,它对应了文件内核对象的所在。 - 获得文件内核对象的句柄后,再次发起“读取”文件的请求 -->
- 告诉R3层,要读取的内核对象是哪个?(句柄的意义) -->
- 通过R3层的检测 -->
-
-
-
-
-
-
- 来到R0层 -->
- 文件内核管理模块,解读句柄,获取必要参数 -->
- 指向开辟的共享区域的文件所在,让R3层读取具体文件信息 <--||
- 文件内核管理模块,解读句柄,获取必要参数 -->
- 来到R0层 -->
-
-
-
-
-
- 句柄: 代表了某个“内核对象”,内核对象是一类事务的抽象
- 006 设备的打开方式 初步整理:
- 文件 CreateFile(路径名或UNC路径)
- UNC路径:局域网路径
- 目录 CreateFile(路径名或UNC路径)
- 需要FILE_FLAG_BACKUP_SEMANTICS标志
- 逻辑磁盘 CreateFile(\\.\?:)
- “\\.”代表 本机;
- “?”代表 盘符;
- 物理磁盘 CreateFile(\\.\PHYSICALDRIVE?)
- 固定格式:\PHYSICALDRIVE?
- "\PHYSICALDRIVE" 代表物理磁盘;
- "?" 这里代表物理磁盘的编号,一般为数字。
- 串口 CreateFile(COM?)
- 并口 CreateFile(LPT?)
- 邮件槽服务器 CreateMailslot(\\.\mailslot\邮件槽名)
- 邮件槽客户端 CreateFile(\\servername\mailslot\邮件槽名)
- 命名管道服务器 CreateNamePipe(\\.\pipe\管道名)
- 命名管道客户端 CreateFile(\\servername\pipe\管道名)
- 匿名管道 CreatePipe
- 套接字 Socket , accept