核心编程第五版第十章中说的每个文件内核对象都有自己的文件指针。并给出例子:
BYTE pb[10];
DWORD dwNumBytes;
HANDLE hFile1=CreateFile(TEXT("MyFile.dat"),...);//Pointer set to 0
HANDLE hFile2=CreateFile(TEXT("MyFile.dat"),...);//Pointer set to 0
ReadFile(hFile1,pb,10,&dwNumBytes,NULL);//Reads bytes 0--9
ReadFile(hFile2,pb,10,&dwNumBytes,NULL);//Reads bytes 0--9
在这个例子中,使用了两个不同的内核对象来管理同一个文件。由于每个内核对象都有自己的文件指针,用一个文件对象来对文件进行操作不会影响到其他对象的文件指针,因此文件的前10个字节被读取了两次。
这个还比较容易理解:进程创建时,OS会为进程构造一个句柄表,当该进程希望获得一个内核对象句柄或者创建一个内核对象从而获得该对象句柄时,系统会在句柄表中增加一个表项,会把这个返回的句柄放置在进程的句柄表中。
上述代码创建了2个文件内核对象,因此在主调进程的句柄表中会放置两个句柄(hFile1,hFile2),分别对应两个内核对象,也就分别有一个属于自己的文件指针,所以上述结果合理。
接下来对书中代码进行了测试:
#include<iostream>
#include<windows.h>
using namespace std;
int main(int argc,char * argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(si));
si.cb=sizeof(si);
ZeroMemory(&pi,sizeof(pi));
CreateProcess(NULL,"notepad.exe 23.txt",NULL,NULL,FALSE,0,NULL,NULL,
&si,&pi);
BYTE pb[11]={0};
DWORD dwNumBytes;
HANDLE hFile1=CreateFile("12.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
HANDLE hFile2=NULL;//=CreateFile("12.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
//DuplicateHandle(GetCurrentProcess(),hFile1,pi.hProcess,&hFile2,0,FALSE,DUPLICATE_SAME_ACCESS);//测试1
DuplicateHandle(GetCurrentProcess(),hFile1,GetCurrentProcess(),&hFile2,0,FALSE,DUPLICATE_SAME_ACCESS);//测试2
ReadFile(hFile1,pb,10,&dwNumBytes,NULL);
cout<<pb<<endl;
ReadFile(hFile2,pb,10,&dwNumBytes,NULL);
cout<<pb<<endl;
CloseHandle(hFile1);
CloseHandle(hFile2);
system("pause");
return 0;
}
自己对于测试2的理解:
DuplicataHandle是复制句柄,把源进程中的某个句柄复制到目的进程中,得到了在目的进程中的一个句柄值(当然源进程可以跟目标进程相同---GetCurrentProcess返回的是伪句柄。。。不再讨论),上述代码刚好是源进程句柄跟目标句柄进程相同(都用了GetCurrentProcess得到当前进程的伪句柄--可以只在本进程内使用),然后这个进程的进程句柄表中已经有了这个文件的句柄了,也就是hFile1,现在在把这个文件句柄hFile1复制到这个进程中?首先想到的是多此一举,其实不完全是,起码增加了这个内核对象中的引用计数了,我的意思是既然这个句柄hFile1已经在这个进程句柄表中了,那现在在复制一次是不是应该跟原来的句柄值一样呢?仅仅只是让引用计数从1变成2.然而我调试发现,这里的hFile1!=hFile2,这里比较困惑,按理说应该相等才对吧?毕竟只有一个文件内核对象,而非2个。请问这里该如何理解,谢谢先!
对于测试1的理解:
由于把文件句柄复制到了其他的进程,则其他进程的进程句柄表中势必会有此文件句柄用来表示该文件,但是这个进程并没有因此创建一个文件内核对象(只有文件内核对象才有一个文件指针的),因此何来文件指针呢?更何况后面还读取了10个字节呢?DuplicateHandle只是复制句柄(MSDN的解释没发现其他内容)这里也迷茫了,请大家帮忙理解一下,三克油三克油!!!
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法