ccwss000
驱动牛犊
驱动牛犊
  • 注册日期2003-12-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分85分
  • 威望9点
  • 贡献值1点
  • 好评度8点
  • 原创分0分
  • 专家分0分
阅读:1043回复:6

请问W2000对较大文件读取的问题,谢谢啦

楼主#
更多 发布于:2004-02-25 17:00
  假定IRP_MJ_READ对应例程ReadFiles,IRP_MJ_WRITE对应例程WriteFiles,编译安装以后用SoftIce观察,发现如果保存一个较大的文件(比如400k)时每次执行WriteFiles最多处理65536个字节,而且除了最后的零头每次都会写65536个字节,但是执行ReadFiles会出现4096,61440,65536等各种情况,这让我不能理解。
  请问请问W2000下对较大文件写的时候IRP_MJ_READ和IRP_MJ_WRITE对应的例程是怎么执行的,读的时候又是怎么执行的?
  谢谢大家啦
changjt
驱动牛犊
驱动牛犊
  • 注册日期2002-12-09
  • 最后登录2010-01-27
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-02-25 19:47
Win2000默认的transfer size就是64KB,所以通过文件系统操作时IRP_MJ_READ和IRP_MJ_WRITE每次最多可处理的字节只有65536,由于预读和延迟写的特性,预读时,通过缺页错误将文件以4KB内存页的单位读入内存,至于预读的size,好像跟文件大小有关,是4KB的倍数,读满一个64KB块以后才会有延迟写发生,这样就可以保证每次都有64KB可写入了,利于性能的提升。
ccwss000
驱动牛犊
驱动牛犊
  • 注册日期2003-12-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分85分
  • 威望9点
  • 贡献值1点
  • 好评度8点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-02-26 16:35
谢谢changjt的解答,我有一个向文件夹内粘贴文件的例子(是个JPEG格式的文件),下面是用SoftIce对粘贴过程进行跟踪的部分信息。
请帮我看一下吧。
IRP_MJ_READ对应ReadFromFile例程,IRP_MJ_WRITE对应WriteToFile例程,写文件部分:
1   ReadFromFile: IrpSp->Parameters.Read.Length = 0x10000
2   WriteToFile: IrpStack->Parameters.Write.Length = 0x10000
3 WriteToFile: IrpStack->Parameters.Write.Length = 0x10000
4   WriteToFile: IrpStack->Parameters.Write.Length = 0x10000

5 WriteToFile: IrpStack->Parameters.Write.Length = 0x10000
6   WriteToFile: IrpStack->Parameters.Write.Length = 0x7000
7   WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
8   WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
9   WriteToFile: IrpStack->Parameters.Write.Length = 0x10000
10 WriteToFile: IrpStack->Parameters.Write.Length = 0x6000
11 WriteToFile: IrpStack->Parameters.Write.Length = 0x10000

注意到3、4、5、9、10、11长度相加之和为352256正好等于文件所占空间大小,
因此本菜鸟认为3、4、5、9、10、11是真正写文件的部分。

读取文件预览部分:
12 ReadFromFile: IrpSp->Parameters.Read.Length = 0x18
13 ReadFromFile: IrpSp->Parameters.Read.Length = 0x1000
14 ReadFromFile: IrpSp->Parameters.Read.Length = 0x10000
15 ReadFromFile: IrpSp->Parameters.Read.Length = 0x18
16 ReadFromFile: IrpSp->Parameters.Read.Length = 0x1000
17 WriteToFile: IrpStack->Parameters.Write.Length = 0x7000
18 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
19 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
20 ReadFromFile: IrpSp->Parameters.Read.Length = 0x10000
21 ReadFromFile: IrpSp->Parameters.Read.Length = 0x18
22 ReadFromFile: IrpSp->Parameters.Read.Length = 0x1000
23 ReadFromFile: IrpSp->Parameters.Read.Length = 0x10000
24 ReadFromFile: IrpSp->Parameters.Read.Length = 0x200
25 ReadFromFile: IrpSp->Parameters.Read.Length = 0x1000
26 ReadFromFile: IrpSp->Parameters.Read.Length = 0x10000
27 ReadFromFile: IrpSp->Parameters.Read.Length = 0xf000

28 WriteToFile: IrpStack->Parameters.Write.Length = 0x7000
29 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
30 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
31 ReadFromFile: IrpSp->Parameters.Read.Length = 0x10000
32 ReadFromFile: IrpSp->Parameters.Read.Length = 0x10000
33 ReadFromFile: IrpSp->Parameters.Read.Length = 0x6000

由于33之后生成的文件预览刚好显示出来,并且23、25、26、27、31、32、33
长度相加之和为352256正好等于文件所占空间大小,因此本菜鸟认为23、25、26、27、31、32、33是真正读取文件的部分。

34 WriteToFile: IrpStack->Parameters.Write.Length = 0x8000
35 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
36 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
37 WriteToFile: IrpStack->Parameters.Write.Length = 0x8000
38 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
39 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
40 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
41 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
42 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
43 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
44 WriteToFile: IrpStack->Parameters.Write.Length = 0x2000
45 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
46 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
47 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
48 WriteToFile: IrpStack->Parameters.Write.Length = 0x1000
......
不知道红色部分偶分析的对不对,并且开头ReadFromFile和WriteToFile两个例程各处理了
64k字节是怎么回事?
读文件部分为什么会有把64k分成4k和60k的情况?
另外在跟踪过程中发现例程ReadFromFile只有在涉及文价操作时才被调用,而例程WriteToFile一直在
被循环调用,那么操作系统是怎么对IRP_MJ_READ和IRP_MJ_WRITE支配的呢?
还有一个问题是,,上面获得文件占用空间大小是352256,而我想获得文件实际内容(大小为350556个字节),如何得到呢?

[编辑 -  2/26/04 by  ccwss000]
changjt
驱动牛犊
驱动牛犊
  • 注册日期2002-12-09
  • 最后登录2010-01-27
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-02-27 08:11
你这样进行分析肯定不行,很多数据都是凑出来的。
首先,你无法在一个纯环境里作分析,因为Ntfs文件系统在OS运行过程中会不时的进行同步操作,譬如更新$MFT、$LogFile、$Bitmap等,所以例程WriteToFile会被系统不断地调用。因此你首先必须从所抓下的读写过程里区分出哪些属于你粘贴文件引起的操作,哪些是系统自身的动作。这个工作用softice分析不太适当,建议使用一些文件系统过滤程序来做,如filemon,这样可以根据文件名来判断。
ccwss000
驱动牛犊
驱动牛犊
  • 注册日期2003-12-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分85分
  • 威望9点
  • 贡献值1点
  • 好评度8点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-02-27 09:33
谢谢changjt的解答,那我现在需要解决这个问题,上面获得文件占用空间大小是352256,而我想获得文件实际内容(大小为350556个字节),如何得到呢?
changjt
驱动牛犊
驱动牛犊
  • 注册日期2002-12-09
  • 最后登录2010-01-27
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-02-27 16:24
通过发FAST_IO_QUERY_STANDARD_INFO获得FILE_STANDARD_INFORMATION
ccwss000
驱动牛犊
驱动牛犊
  • 注册日期2003-12-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分85分
  • 威望9点
  • 贡献值1点
  • 好评度8点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-03-01 12:28
谢谢changjt的解答,以后继续给予指导
游客

返回顶部