跨进程使用句柄和文件操作

使用句柄

1. 跨进程使用句柄

  1)子进程继承父进程句柄的方式

将父进程的句柄放到子进程的句柄表里

     1- 句柄本身可以被继承

     2- Createprocess的参数bInheritHandles为TRUE

     3- 继承已经打开的句柄

  SECURITY_ATTRIBUTES sa;

  sa.nLength = sizeof(sa);

  sa.lpSecurityDescriptor = NULL;

 

2) 非父子进程使用句柄或者,在创建子进程之后打开的句柄

     复制句柄  -- DuplicateHandle

  HANDLE hTargetHandle;

  DuplicateHandle(

    GetCurrentProcess(),//源进程的进程句柄

    hProcess, //拷贝的句柄

    hProcessDst, //目标进程的进程句柄

    &hTargetHandle, //给目标进程使用的值

    0, //忽略

    FALSE,

    DUPLICATE_SAME_ACCESS); //目标进程的句柄和源进程的句柄有相同的权限

 

  3) 窗口句柄可以直接跨进程使用

 

 

2. 进程间的通信

   2.1 消息和WM_COPYDATA

       1) 自定义消息 --参数不够用

       2) WM_COPYDATA

       通过WM_COPYDATA传递消息,操作系统会首先将发送的数据拷贝到高2GB共享区,然后再拷贝到接收方的用户空间中,所以会有两次拷贝,因此在数据量不大的时候,可以使用此方法。

使用 WM_COPYDATA 在进程间共享数据

 

消息作用:

    在进程间共享数据(内部通过创建内存映射文件)

 

消息介绍:

需要用到的数据结构/类型:

typedef struct tagCOPYDATASTRUCT {

    ULONG_PTR dwData;

    DWORD cbData;

    PVOID lpData;

} COPYDATASTRUCT, *PCOPYDATASTRUCT;

 

结构体参数说明:

    dwData(ULONG)   保存一个数值, 可以用来作标志等

    lpData(void*)   待发送的数据的起始地址(可以为NULL)

    cbData(DWORD)   待发送的数据的长度

    

消息的参数:

    hWnd:   接收数据的窗口的句柄

    wParam: 传送该数据的窗口句柄(NULL也无所谓)

    lParam: COPYDATASTRUCT类型变量的地址

    

使用示例:

    COPYDATASTRUCT cds;

    char msg[] = "女孩不哭";

    cds.dwData = 0;

    cds.lpData = msg;

    cds.cbData = strlen(msg)+1; //字符串请记得把'\0'加上, 不然就错了, 这里是ANSI字符串

    SendMessage(FindWindow("nbsg_class", NULL), WM_COPYDATA, 0, (LPARAM)&cds);

    

接收端对该消息的一种可能处理:

    case WM_COPYDATA:

    {

        //这里的消息应该是以 '\0' 结尾的字符串

        COPYDATASTRUCT* pCDS = (COPYDATASTRUCT*)lParam;

        MessageBox(hWnd, pCDS->lpData, "", MB_OK);

        return TRUE;

    }

    

说明:  
    发送的数据可以是任意的, 我上面只是为了用MessageBox做测试, 所以发送的是以'\0'的字符串.
    如果接收消息的应用程序处理了该消息, 它应该返回 TRUE , 否则返回 FALSE.

    lpData 指向的内存应该是一段"数据", 就是说里面不应该有指向该程序某数据的指针. 因为 SendMessage 在处理 WM_COPYDATA , 只是把 lpData 指向的 cbData 个字节复制到共享内存中. 当前进程私有的指针就算是被发送到接收程序, 其也是无法访问的.

    当该消息正当发送时, 该进程的其它线程不能修改其中的数据.

    接收端应用程序应该把这段共享内存作为只读内存来访问. 请不要尝试修改其中的内容.

lParam 指向的数据只有在该消息处理时有效, 消息返回后无效(共享内存已被释放). 且接收端也不能释放该内存. 如果要在消息返回后继续取得数据, 可以把它复制到当前进程的某个位置.

 

 共享段

      1) 在dll中创建一个共享段,并在共享段中定义数据

#pragma data_seg( "CR33_DATA" )  //起始位置

int  g_nVal = 9;

char szBuff[MAXBYTE] = { "hell world" };

#pragma data_seg() //结束位置

 

      2) 将共享段的属性设置为可读,可写,可共享(重点)

#pragma comment(linker, "/SECTION:CR33_DATA,RWS")

 

      3) 导出共享段中定义的数据

 

 

 文件操作

   打开文件 CreateFile

   关闭文件 CloseHandle

    ReadFile

    WriteFile

   文件指针 SetFilePointer

   文件的大小 GetFileSize

 

1. CreateFile

这个函数的功能是创建或者打开一个文件或者I/O设备,通常使用的I/O形式有文件、文件流、目录、物理磁盘、卷、终端流等。如执行成功,则返回文件句柄。 INVALID_HANDLE_VALUE 表示出错,会设置 GetLastError 。

 

HANDLE CreateFile(

LPCTSTR lpFileName, //普通文件名或者设备文件名

DWORD dwDesiredAccess, //访问模式(写/读)

DWORD dwShareMode, //共享模式

LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针

DWORD dwCreationDisposition, //如何创建

DWORD dwFlagsAndAttributes, //文件属性

HANDLE hTemplateFile //用于复制文件句柄

)

参数 

类型描述

lpFileName

String ,要打开的文件的名字

dwDesiredAccess

Long ,如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息

dwShareMode

Long ,零表示不共享; FILE_SHARE_READ 和 / 或 FILE_SHARE_WRITE 表示允许对文件进行共享访问

lpSecurityAttributes

SECURITY_ATTRIBUTES ,指向一个 SECURITY_ATTRIBUTES 结构的指针,定义了文件的安全特性(如果操作系统支持的话)

dwCreationDisposition

Long ,下述常数之一:

CREATE_NEW 创建文件; 如文件存在则会出错

CREATE_ALWAYS 创建文件,会改写前一个文件;相当于删除原来文件重新写入。文件如果不存在会创建文件。

OPEN_EXISTING 文件必须已经存在。由设备提出要求;

OPEN_ALWAYS 如文件不存在则创建它; 

TRUNCATE_EXISTING 将现有文件缩短为零长度

dwFlagsAndAttributes                                             

Long ,一个或多个下述常数:

FLE_ATTRIBUTE_ARCHIVE 标记归档属性;

FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式;

FILE_ATTRIBUTE_NORMAL 默认属性; 

FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录;

FILE_ATTRIBUTE_READONLY 文件为只读;

FILE_ATTRIBUTE_SYSTEM 文件为系统文件;

FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作; FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作;FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块;

FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化;

 FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化 ;

FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件;

hTemplateFile

Long ,如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性

2. ReadFile

从文件指针指向的位置开始将数据读出到一个文件中, 且支持同步和异步操作,如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话,当程序调用成功时,它将实际读出文件的字节数保存到lpNumberOfBytesRead指明的地址空间中。FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作。

BOOL ReadFile(

    HANDLE hFile,                                    //文件的句柄

    LPVOID lpBuffer,               //用于保存读入数据的一个缓冲区

    DWORD nNumberOfBytesToRead,    //要读入的字节数

    LPDWORD lpNumberOfBytesRead,    //指向实际读取字节数的指针

    LPOVERLAPPED lpOverlapped

    //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。

    //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL

);

 WriteFile

BOOL WINAPI WriteFile(

  __in          HANDLE hFile,                   // 文件句柄

  __in          LPCVOID lpBuffer,               // 要写入的数据

  __in          DWORD nNumberOfBytesToWrite,    // 要写入的字节数

  __out         LPDWORD lpNumberOfBytesWritten, // 实际写入的字节数

  __in          LPOVERLAPPED lpOverlapped       // OVERLAPPED 结构,一般设定为 NULL

)  

 

 

posted @ 2020-09-04 13:28  特权E5  阅读(811)  评论(0编辑  收藏  举报