阅读:1043回复:6
请问W2000对较大文件读取的问题,谢谢啦
假定IRP_MJ_READ对应例程ReadFiles,IRP_MJ_WRITE对应例程WriteFiles,编译安装以后用SoftIce观察,发现如果保存一个较大的文件(比如400k)时每次执行WriteFiles最多处理65536个字节,而且除了最后的零头每次都会写65536个字节,但是执行ReadFiles会出现4096,61440,65536等各种情况,这让我不能理解。
请问请问W2000下对较大文件写的时候IRP_MJ_READ和IRP_MJ_WRITE对应的例程是怎么执行的,读的时候又是怎么执行的? 谢谢大家啦 |
|
沙发#
发布于:2004-02-25 19:47
Win2000默认的transfer size就是64KB,所以通过文件系统操作时IRP_MJ_READ和IRP_MJ_WRITE每次最多可处理的字节只有65536,由于预读和延迟写的特性,预读时,通过缺页错误将文件以4KB内存页的单位读入内存,至于预读的size,好像跟文件大小有关,是4KB的倍数,读满一个64KB块以后才会有延迟写发生,这样就可以保证每次都有64KB可写入了,利于性能的提升。
|
|
板凳#
发布于: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] |
|
地板#
发布于:2004-02-27 08:11
你这样进行分析肯定不行,很多数据都是凑出来的。
首先,你无法在一个纯环境里作分析,因为Ntfs文件系统在OS运行过程中会不时的进行同步操作,譬如更新$MFT、$LogFile、$Bitmap等,所以例程WriteToFile会被系统不断地调用。因此你首先必须从所抓下的读写过程里区分出哪些属于你粘贴文件引起的操作,哪些是系统自身的动作。这个工作用softice分析不太适当,建议使用一些文件系统过滤程序来做,如filemon,这样可以根据文件名来判断。 |
|
地下室#
发布于:2004-02-27 09:33
谢谢changjt的解答,那我现在需要解决这个问题,上面获得文件占用空间大小是352256,而我想获得文件实际内容(大小为350556个字节),如何得到呢?
|
|
5楼#
发布于:2004-02-27 16:24
通过发FAST_IO_QUERY_STANDARD_INFO获得FILE_STANDARD_INFORMATION
|
|
6楼#
发布于:2004-03-01 12:28
谢谢changjt的解答,以后继续给予指导
|
|