1、通过“句柄继承”实现内核对象的共享
父进程代码:
#include "stdafx.h"
#include <Windows.h>
#define MAX_BUFFER_SIZE 2048
int main(int argc,char * argv[])
{
// 定义用于操作文件时要用到的变量
HANDLE hFile;
LPVOID lpFileBuffer;
DWORD dwBytesInFile;
int iResult;
// 创建一个安全属性对象
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
// 打开一个文件
hFile = CreateFile("robots.txt", // 要创建或打开对象的名字
GENERIC_READ, // 访问对象的方式
FILE_SHARE_READ, // 指定对象的共享方式
&sa, // 安全属性
OPEN_EXISTING, // 对象创建标志(这里要打开一个已经存在的文件,否则函数会执行失败)
FILE_ATTRIBUTE_NORMAL, // 指定文件的属性和标志
NULL);
if(hFile == INVALID_HANDLE_VALUE){
printf("Create file handle failed.(%d)\n",GetLastError());
return 1;
}
lpFileBuffer = HeapAlloc(GetProcessHeap(), // 堆句柄
0, // 堆分配控制标志
MAX_BUFFER_SIZE); // 分配的字节数
while(1){
iResult = ReadFile(hFile, //
lpFileBuffer,
MAX_BUFFER_SIZE, // 指定要从文件中读取的字节数。
&dwBytesInFile, // 接收的字节数
NULL);
if(!iResult){
printf("Read file failed.(%d)\n",GetLastError());
CloseHandle(hFile);
return 1;
}
if(dwBytesInFile > MAX_BUFFER_SIZE){
HeapReAlloc(GetProcessHeap(), // 堆句柄
0, // 在更改内存块大小时,所使用的标志
lpFileBuffer, // 再分配内存块的指针
dwBytesInFile); // 再分配的字节数
ZeroMemory(lpFileBuffer,dwBytesInFile);
}else{
break;
}
}
printf("Parent process id:%d\n",GetCurrentProcessId());
printf("[Parent]The value of the handle is %u\n",hFile);
printf("[Parent]The index of the handle in table is:%u\n",((DWORD)hFile/4));
printf("[Parent]The content of the robots.txt:\n%s\n\n\n",lpFileBuffer);
//最好将要传递给子进程参数命令行的值存放在缓存中
LPSTR lpCommandLine; //定义一个字符串指针以存放内核对象句柄
lpCommandLine = (LPSTR)HeapAlloc(GetProcessHeap(),0,256); //为字符串指针分配内存
ZeroMemory(lpCommandLine, 256);
ltoa((DWORD)hFile,lpCommandLine,10); //将HANDLE句柄转换为字符串类型储存
// 定义创建进程时,要用到的两个对象
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi,sizeof(pi));
BOOL bRet = CreateProcess("..\\Debug\\ChildProcess.exe", // 新进程要执行的可执行文件名称
lpCommandLine, // 要传递给新进程的命令行字符串
NULL, // 进程的安全属性
NULL, // 线程的安全属性
TRUE, // 是否可以被继承
0, // 创建标志
NULL, // 新进程要使用的环境字符串
NULL, // 子进程的当前目录
&si,
&pi);
if (!bRet)
{
printf("Create child process failed.(%d)\n",GetLastError());
return 1;
}
printf("Child process created successed.\n\n\n");
CloseHandle(hFile);
WaitForSingleObject(pi.hProcess,INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
system("pause");
return 0;
}
子进程代码:
#include <iostream>
#include <Windows.h>
using std::cout;
using std::endl;
#define MAX_BUFFER_SIZE 1024
int main(int argc,char * argv[])
{
printf("子进程开始读文件...\n\n");
int iResult;
LPSTR lpFileBuffer;
DWORD dwBytesHasRead;
LPSTR commandLine = GetCommandLine();
HANDLE hChildFile = (HANDLE)atol(commandLine);
lpFileBuffer = (LPSTR)HeapAlloc(GetProcessHeap(),0,MAX_BUFFER_SIZE);
// 移动一个打开文件的指针
SetFilePointer(hChildFile, // 文件句柄
NULL, // 偏移量(低位)
NULL, // 偏移量(高位)
FILE_BEGIN); // 基准位置(FILE_BEGIN:文件开始位置 FILE_CURRENT:文件当前位置 FILE_END:文件结束位置)
iResult = ReadFile(hChildFile,lpFileBuffer,MAX_BUFFER_SIZE,&dwBytesHasRead,NULL);
if(!iResult){
printf("Read file failed.(%d)\n",GetLastError());
CloseHandle(hChildFile);
return 1;
}
printf("Child process id:%d\n",GetCurrentProcessId());
printf("[Child]The value of the handle is %u\n",(DWORD)hChildFile);
printf("[Child]The index of the handle in table is:%u\n",((DWORD)hChildFile/4));
printf("[Child]The content of the robots.txt:\n%s\n\n\n",lpFileBuffer);
CloseHandle(hChildFile);
return 0;
}