异步文件操作的疑惑,望高手解答

jishufenxi 2008-07-27 05:45:05
一个基于iocp的异步文件操作测试

文件是这样创建的:
m_File=CreateFile("c:\abc.DAT",GENERIC_READ ¦GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_FLAG_OVERLAPPED,NULL);

写函数定义:
void Write(char* Buffer,int WriteCount,int WriteOff)
{
LPOVERLAPPED OL;
memset(&OL,0,sizeof(LPOVERLAPPED));
OL.Offset=WriteOff;
DWORD nWritten;
if(!WriteFile(m_File,Buffer, WriteCount, &nWritten,(LPOVERLAPPED)&OL))
{
DWORD Error=GetLastError();
if(Error!=ERROR_IO_PENDING && Error!=ERROR_HANDLE_EOF)
throw CError(FormatErrorMessage(Error));
}
}

测试代码1:
char *Buffer=new char[2000000];
for(int n=0;n <10;n++)
{
int off=n*2000000;
Write(Buffer+off,2000000,off);
}

测试代码2:
char *Buffer=new char[2000000];
for(int n=0;n <10000;n++)
{
int off=n*2000;
Write(Buffer+off,2000,off);
}

运行测试出现的现象:
对新建的未执行过写入操作的文件,测试代码1是异步写入的,对执行过写入操作即文件长度>0的文件却是同步写入的。测试代码2始终都是异步执行的。
进一步测试发现是同步还是异步取决于单次写入的字节数,写入的字节数小就是异步的,字节数大到一定程度就变成同步了。
请问是怎么回事?
...全文
167 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
iPengbei 2011-05-13
  • 打赏
  • 举报
回复
  LPOVERLAPPED OL;  
memset(&OL,0,sizeof(LPOVERLAPPED));

这是一个明显的错误!LPOVERLAPPED是个指针类型!
zzultc 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 jishufenxi 的回复:]
to cnzdgs:
我是在主线程(界面线程)调用测试代码的,如果同步操作,则主线程在操作返回前是阻塞的,界面失去响应。
[/Quote]
我估计是这样的:
测试代码1,只有10次循环,当然可以快速返回,
而对代码2,有10000次循环,当然慢得多。
你根据界面线程的反应恐怕是断定不出来。
ringphone 2008-07-28
  • 打赏
  • 举报
回复
关注
不过一直有个疑惑,异步写入有什么好处?怕阻塞界面在线程里写就是了。
zzultc 2008-07-28
  • 打赏
  • 举报
回复
还是楼主细心,学习了。
jishufenxi 2008-07-28
  • 打赏
  • 举报
回复
to ringphone:
异步IO的好处就是用一个线程支持大量并发IO。如果使用线程池来支持并发IO,一是需要进出临界区耗费大量资源、二是线程切换耗费大量资源,感觉服务器上还是单线程异步IO合适
jishufenxi 2008-07-28
  • 打赏
  • 举报
回复
to zzultc:你看错了,是测试代码2比测试代码1返回快
hikuers 2008-07-27
  • 打赏
  • 举报
回复
mark
cnzdgs 2008-07-27
  • 打赏
  • 举报
回复
要测试异步操作可以在CreateFile时使用FILE_FLAG_NO_BUFFERING标志,以免系统磁盘缓冲影响,不过要注意必须整扇区读写(通常情况读写的开始位置和长度都用512的整数倍即可)。
shanying_0 2008-07-27
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 gaoteng1984 的回复:]
引用 2 楼 hhhh63 的回复:
异步写入文件的过程是把文件放到内存缓冲中,然后由后台程序将缓冲中的数据写入磁盘中。
当一次写入的字节数大到一定程度时,缓冲字节不够了,就变成同步了。

WriteFile好像并不把数据先拷贝到缓冲区,我看到MSDN上这段话:
Accessing the output buffer while a write operation is using the buffer may lead to corruption of the data written from that buffer. Applications must not …
[/Quote]

我记得c语言是支持缓冲写文件的.比如fwrite等函数.

在msdn上
CFile is the base class for Microsoft Foundation file classes. It directly provides unbuffered, binary disk input/output services, and it indirectly supports text files and memory files through its derived classes
cfile类是不支持缓冲写入的。ms封装的cfile类也是调用的plat sdk的函数.由此推断.plat sdk的writefile也不具备缓冲写入的功能
gaoteng1984 2008-07-27
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 hhhh63 的回复:]
异步写入文件的过程是把文件放到内存缓冲中,然后由后台程序将缓冲中的数据写入磁盘中。
当一次写入的字节数大到一定程度时,缓冲字节不够了,就变成同步了。
[/Quote]
WriteFile好像并不把数据先拷贝到缓冲区,我看到MSDN上这段话:
Accessing the output buffer while a write operation is using the buffer may lead to corruption of the data written from that buffer. Applications must not write to, reallocate, or free the output buffer that a write operation is using until the write operation completes.
即WriteFile需要用到参数里的数据,在结束之前用户不要动这个数据区。那么很可能没有数据拷贝这一过程。
jishufenxi 2008-07-27
  • 打赏
  • 举报
回复
问题似乎确实如同hhhh63所说。进一步测试发现每次写入150000字节以下数据是异步执行,否则是同步执行,而读取操作似乎没有限制
jishufenxi 2008-07-27
  • 打赏
  • 举报
回复
to cnzdgs:
我是在主线程(界面线程)调用测试代码的,如果同步操作,则主线程在操作返回前是阻塞的,界面失去响应。
hhhh63 2008-07-27
  • 打赏
  • 举报
回复
异步写入文件的过程是把文件放到内存缓冲中,然后由后台程序将缓冲中的数据写入磁盘中。

当一次写入的字节数大到一定程度时,缓冲字节不够了,就变成同步了。
cnzdgs 2008-07-27
  • 打赏
  • 举报
回复
你是怎么确定各次写入操作是同步还是异步的?

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧