Windows操作系统中的I/O(读/写 输入/输出)
导言
写一个Windows平台下的应用程序大多时候都是离不开读写文件,网络通信的。
比如一个服务应用程序来说,它可能从网络适配器接受用户的请求,对请求进行处理计算,最终将用户端所需的数据返回,中间可能还涉及到对磁盘的读写,这些都是I/O操作,所以,要设计一个稳健的,高效的,伸缩性好的应用程序,就必须将Windows的I/O机制搞清楚。
一、 两种 读/写 机制
输入Input / 输出Output,有两种机制,他们是:
1 同步I/O: 线程执行一个输入输出函数时,输入输出工作执行完毕后,函数返回继续执行以后的代码。
2 异步I/O: 线程执行一个输入输出函数时,函数不等待读/写操作完成便立即返回,线程可先去执行下文,执行下文时可查询刚刚发起的读/写操作是否完成。
解读:
可以看出,异步I/O是更加高效的,同步I/O将会阻塞线程的执行,不应该被提倡。
有时候我们会认为,我们为每次执行I/O操作的时候,新开一个线程,让他去执行同步I/O函数,然后我们的原线程去执行工作,这样做是可以的,但是其实这样就是我们自己模拟实现了异步I/O,其实我们调用异步I/O函数的时候,操作系统内部也是维护了一个新线程去为我们进行I/O操作的。
但是,新建线程是一件很耗费CPU资源的事情,而且I/O操作时,CPU需要计算,需要从磁盘或网络适配器的缓冲区,将数据读取到内存中,或者将内存中的数据写到磁盘或网络适配器的缓冲区里,所以,I/O操作的线程不是睡眠的,而是忙碌的,所以我们得出了一个结论,如果我们的计算机上只有两个CPU,同时执行的I/O线程超过两个以上时,CPU会因为I/O线程不是睡眠的而分配给他们时间片,于是线程间的频繁切换,也会降低我们的应用程序的性能。
那么,我们得出结论:同时执行的I/O线程的数量不应该大于CPU数量,客户发起的I/O请求需要一个队列,每次并发处理的I/O操作应该等于CPU数量,如果并发处理的I/O请求数量太多,CPU切换过于频繁,会将CPU资源浪费在线程切换上,从而严重降低程序性能。
二、读/写 前后的工作:创建与释放要读/写的设备的内核对象
要对设备进行读/写,必须先知道创建一个用于该设备的读写的内核对象,在读/写之后,释放该内核对象。
1. 创建I/O内核对象的函数: CreateFile(...) 与其他内核对象一样,我们获取的仅仅是一个句柄。
2. 关闭I/O内核对象的函数: CloseHandle(...)
解读:

HANDLE CreateFile(
LPCTSTR lpFileName, //要读写的设备
DWORD dwDesiredAccess, //访问模式:0(不读写,如改变设备配置) GENERIC_READ,GENERIC_WRITE(可异或)
DWORD dwShareMode, //共享模式:FILE_SHARE_DELETE FILE_SHARE_READ FILE_SHARE_WRITE
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性 里面可设置内核对象的继承性
DWORD dwCreationDistribution, //创建方式 CREATE_NEW CREATE_ALWAYS OPEN_EXISTING OPEN_ALWAYS TRUNCATE_EXISTING
DWORD dwFlagsAndAttributes, //文件属性和标志
HANDLE hTemplateFile //文件属性模板,如指定了这个参数,则忽略上个参数中的文件属性
);
/*
参数 dwFlagsAndAttributes
1)文件属性:
(FILE_ATTRIBUTE_)ARCHIVE COMPRESSED HIDDEN NORMAL OFFLINE READONLY SYSTEM TEMPORARY
2)标志:
(FILE_FLAG_)WRITE_THROUGH OVERLAPPED NO_BUFFERING RANDOM_ACCESS SEQUENTIAL_SCAN DELETE_ON_CLOSE BACKUP_SEMANTICS POSIX_SEMANTICS
*/

这个CreateFile函数返回了一个文件内核对象句柄,这里说的文件不是狭义上的磁盘文件,也包括一些设备,比如串口,并口,邮件槽,命名管道和匿名管道,另外,有些设备句柄不是通过CreateFile创建的,下面是一个创建设备内核对象的函数的说明表。
设备 创建设备内核对象的函数
文件 CreateFile(pszName为路径名或UNC路径名)。
逻辑磁盘驱动器 CreateFile(pszName为\\.\x:)。x是盘符,打开驱动器可以格式化或者检测该驱动器的大小。
物理磁盘驱动器 CreateFile(pszName为\\.\PHYSICALDRIVEx)。x是物理驱动器序号,比如PHYSICALDRIVE0
串口 CreateFile(pszName为"COMx")
并口 CreateFIle(pszName为"LPTx")
邮件槽服务器 CreateMailslot(pszName为\\.\mailslot\mailslotname)
邮件槽客户端 CreateFile(pszName为\\servername\mailslot\mailslotname)
命名管道服务器 CreateNamedPipe(pszName为\\.\pipe\pipename)
命名管道客户端 CreateFile(pszName为\\servername\pipe\pipename)
匿名管道 CreatePipe
套接字 Socket,accept或AcceptEx
控制台 CreateConsoleScreenBuffer或GetStdHandle
以上这些函数,会创建一个I/O内核对象,并取得该对象的句柄值,然后我们可以调用与具体设备相关的函数,并传入得到的设备内核对象句柄,来和设备进行通信。
和其他内核对象一样,可以调用函数CloseHandle来关闭CreateFile创建的I/O内核对象。
BOOL CloseHandle(HANDLE hObject);
但是如果设备是套接字,就必须调用closesocket。
int closesocket(SOCKET s);
如果有一个设备句柄,可以通过GetFileType来查处具体的设备类型。
DWORD GetFileType(HANDLE hDevice);
返回值为:
| 值 | 描述 |
| FILE_TYPE_UNKNOWN | 未知类型 |
| FILE_TYPE_DISK | 磁盘文件 |
| FILE_TYPE_CHAR | 字符文件,一般是并口设备或者控制台设备 |
| FIEL_TYPE_PIPE | 指定的文件时一个命名管道或匿名管道 |
Windows操作系统中的I/O(读/写 输入/输出)的更多相关文章
- WINDOWS操作系统中可以允许最大的线程数(线程栈预留1M空间)(56篇Windows博客值得一看)
WINDOWS操作系统中可以允许最大的线程数 默认情况下,一个线程的栈要预留1M的内存空间 而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程 但是内存当然不可能完全拿来 ...
- 在Windows操作系统中,如何终止占有的8080端口的tomcat进程
在Windows操作系统中,我们在启动一个tomcat服务器时,经常会发现8080端口已经被占用的错误,而我们又不知道如何停止这个tomcat服务器. 本文将通过命令来强行终止这个已经运行的tomca ...
- CVE-2019-0797漏洞:Windows操作系统中的新零日在攻击中被利用
https://securelist.com/cve-2019-0797-zero-day-vulnerability/89885/ 前言 在2019年2月,卡巴实验室的自动漏洞防护(AEP)系统检测 ...
- windows操作系统中安装、启动和卸载memcached
今天总结一下如何在Windows操作系统中安装.启动和卸载memcached:下载地址: http://download.csdn.net/download/wangshuxuncom/8249501 ...
- Ant—怎样Windows操作系统中搭建Apache Ant环境
介绍一下怎样在Windows操作系统中搭建Apache Ant环境: 一.下载Apache Ant压缩文件:http://download.csdn.net/detail/wangshuxuncom/ ...
- 在windows操作系统中,查询端口占用和清除端口占用的程序
一.在windows操作系统中,查询端口占用和清除端口占用的程序 提升权限后用:netstat -b或用 1.查询端口占用的进程ID 点击"开始"-->"运行&qu ...
- Git—怎样Windows操作系统中安装Git
介绍一下怎样在Windows操作系统中安装Git: 一.下载Git安装压缩文件:http://download.csdn.net/detail/wangshuxuncom/8035045 二.解压该压 ...
- [转]在 Windows 操作系统中的已知安全标识符(Sid security identifiers)
安全标识符 (SID) 是用于标识安全主体或安全组在 Windows 操作系统中的可变长度的唯一值.常用 Sid 的 Sid 标识普通用户的一组或通用组.跨所有操作系统,它们的值保持不变. 此信息可用 ...
- 在Windows操作系统中安装MongoDB
如何在Windows操作系统中安装MongoDB: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/ 启动Mon ...
随机推荐
- Python中的幽灵—编码方式
首先要搞懂本地操作系统编码与系统编码的区别: 本地操作系统编码方式与操作系统有关,Linux默认编码方式为utf-8,Windows默认编码方式为gbk: 系统编码方式与编译器or解释器有关,Pyth ...
- S03_CH03_AXI_DMA_OV7725摄像头采集系统
S03_CH03_AXI_DMA_OV7725摄像头采集系统 3.1概述 本课程讲解如何搭建基于DMA的图形系统,方案原理如下. 摄像头采样图像数据后通过DMA送入到DDR,在PS部分产生DMA接收中 ...
- (转)查找算法:二叉排序树(BSTree)
二叉排序树(Binary Sort Tree),又称为二叉查找树(Binary Search Tree) ,即BSTree. 构造一棵二叉排序树的目的,其实并不是为了排序,而是为了提高查找和插入删除的 ...
- 牛客 133D 挑选队友 (分治FFT)
大意: $n$个人, 分别属于$m$个组, 要求选出$k$个人, 使得每组至少有一人, 求方案数. 显然答案为$\prod((1+x)^{a_i}-1)$的第$k$项系数, 分治$FFT$即可. #i ...
- thymeleaf 模板使用 提取公共页面
切记!!!thymeleaf模板的使用,姿势很重要!!!姿势不对,可能导致样式.js等的使用受到影响 前台开发中,由于页面目录结构不同,可能导致引入的公共页面中的的跳转路径在部分页面能用,部分页面不能 ...
- python+vsCode 环境搭建
先安装python环境和vscode Python下载链接:https://www.python.org/vscode下载地址:https://code.visualstudio.com/ 安装这两个 ...
- SpringBoot 中aop整合方法执行日志
今天事情不多, 处理完手中的事边想着捣鼓一下AOP, 着手开始写才发现, 多久不用, 自己已经忘得差不多了, 捣鼓半天之后, 慢慢整出这个小demo,以便于以后查阅回顾 1 .先创建一个注解, 用来作 ...
- 使用jMeter构造大量并发的随机HTTP请求
在前一篇文章使用jMeter构造大量并发HTTP请求进行微服务性能测试里,我介绍了如何用jMeter构造并发HTTP请求.但是通过文中介绍的方式构造的并发请求,其请求参数都是硬编码的'Wang'. 有 ...
- 【python+beautifulsoup4】Beautifulsoup4
Beautiful soup将复杂HTML文档转换成一个复杂的属性结构,每个节点都是python对象,所有对象可归纳为4种Tag,NavigableString,BeautifulSoup,Comme ...
- HTML5学习:表格
HTML代码 <table> <thead> <tr> <th>标题1</th> <th>标题2</th> < ...