c++怎么在不使用STL的情况下利用Win32 API进行低级文件IO【底层】

千丽小哥_2951

千丽小哥_2951

2026-03-31

1005人浏览

原创

file_flag_no_buffering并非真正“底层”,仅绕过系统缓存;实现低级io需满足缓冲区地址、读写大小及文件偏移均按扇区对齐(如4096字节),且须用virtualalloc等分配对齐内存,否则readfile会返回error_invalid_parameter。

c++怎么在不使用stl的情况下利用win32 api进行低级文件io【底层】

用 CreateFile 打开文件时,FILE_FLAG_NO_BUFFERING 真的等于“底层”吗?

不是。它只是绕过系统缓存,不等于跳过内核、不等于直接和磁盘对话。真正低级 IO 的关键不在标志位,而在你能否控制对齐、缓冲区地址、读写粒度——这些全由 CreateFile 返回的句柄 + ReadFile/WriteFile 决定。

常见错误:开了 FILE_FLAG_NO_BUFFERING 却用普通 malloc 分配缓冲区,结果 ReadFile 直接失败并返回 ERROR_INVALID_PARAMETER。

  • 缓冲区地址必须是磁盘扇区大小(通常是 512 或 4096)对齐的,推荐用 VirtualAlloc(返回页面对齐地址)或 _aligned_malloc(需手动指定对齐值)
  • 每次读写字节数必须是扇区大小的整数倍;偏移量(lpOverlapped->Offset)也必须对齐
  • 文件必须以 CREATE_ALWAYS 或 OPEN_EXISTING 打开,且不能是 CONIN$ 或管道等伪设备

ReadFile 和 WriteFile 在非重叠模式下为什么有时“卡住”?

因为它们默认是同步阻塞的——但“卡”的真实原因是文件句柄没设成 FILE_ATTRIBUTE_NORMAL 或被其他进程独占,或者你试图读一个刚创建但还没落盘的文件(尤其在 FILE_FLAG_NO_BUFFERING 下更敏感)。

使用场景:做日志批量写入、内存映射前预分配、或对接硬件驱动时,需要确定性延迟和可控的完成时机。

  • 确保打开时用了 GENERIC_READ | GENERIC_WRITE,且没有漏掉 FILE_SHARE_READ | FILE_SHARE_WRITE(除非你真要独占)
  • 检查返回值:ReadFile 返回 FALSE 时立刻调 GetLastError(),常见错误如 ERROR_HANDLE_EOF(读到尾)、ERROR_IO_PENDING(误用了重叠句柄却没传 OVERLAPPED)
  • 非重叠模式下,lpNumberOfBytesRead 参数不可为 NULL,否则行为未定义

不用 std::vector,怎么安全管理动态缓冲区?

Win32 本身不提供容器,但你可以用 VirtualAlloc + VirtualFree 搭配手动长度跟踪,比 new[] 更贴近底层控制意图——毕竟页对齐、可设保护属性、能跨进程共享(配合 SEC_COMMIT)。

C++ 算法竞赛自动化测试数据生成与校验框架
C++ 算法竞赛自动化测试数据生成与校验框架

根据原题生成新题面、验证器及完整测试数据,自动套用 testlib 模板,用于用户要求生成测试数据时。

下载

性能影响:每次 VirtualAlloc 至少分配一页(4KB),小缓冲区浪费明显;但大块连续 IO(如 64KB 日志块)时,页表友好、无 malloc 碎片、避免 STL 构造/析构开销。

  • 分配示例:void* buf = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  • 释放必须用 VirtualFree(buf, 0, MEM_RELEASE),不能用 delete[] 或 free
  • 若需零初始化,不要依赖 MEM_COMMIT 的清零保证(NTFS 压缩卷可能不满足),显式调 SecureZeroMemory 或循环赋 0

为什么 SetFilePointerEx 移动位置后 ReadFile 还读错数据?

因为你在用非重叠句柄时,没确认上次 IO 是否真正完成——Win32 文件指针是“逻辑位置”,但底层设备队列可能还在处理上一次请求,尤其在开启 FILE_FLAG_NO_BUFFERING 或对接慢速存储时。

容易踩的坑:把 SetFilePointerEx 当作原子 seek + read 操作,忽略了 IO 完成的时序依赖。

  • 非重叠模式下,SetFilePointerEx 成功只表示指针设好了,不代表磁盘已就绪;后续 ReadFile 才真正触发物理操作
  • 如果之前发过异步 IO(比如忘了重置 OVERLAPPED),当前 ReadFile 可能和旧请求冲突,导致 ERROR_INVALID_HANDLE
  • 调试技巧:用 GetFileSizeEx 校验当前文件大小,再用 SetFilePointerEx 的返回值判断是否越界(返回 FALSE + GetLastError() == ERROR_NEGATIVE_SEEK)

真正的底层控制从来不是靠“不用 STL”来体现的,而是你是否清楚每个 Win32 调用背后对应的 IRP 请求类型、是否检查了所有可能的错误分支、以及有没有把缓冲区生命周期和虚拟内存管理绑在一起。这些细节一旦漏掉,代码表面看能跑,实际在高负载或不同磁盘型号下就会崩得毫无征兆。

大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

529

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1658

6

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.23

616

5

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.27

351

13

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

299

31

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

2023.11.13

2471

4

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.12.29

765

3

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

2026.09.23

80

15

Buffalo框架路由与请求处理实操指南
Buffalo框架路由与请求处理实操指南

本专题讲解Buffalo框架路由与请求处理机制,涵盖路由注册与分组、资源路由、Handler编写规范、Context上下文方法、参数绑定、中间件编写挂载、Session与Cookie读写、Flash消息及错误页面定制方法。

2026.09.23

40

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习