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


    使用句柄

    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; //字符串请记得把''加上, 不然就错了, 这里是ANSI字符串

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

        

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

        case WM_COPYDATA:

        {

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

            COPYDATASTRUCT* pCDS = (COPYDATASTRUCT*)lParam;

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

            return TRUE;

        }

        

    说明:  
        发送的数据可以是任意的, 我上面只是为了用MessageBox做测试, 所以发送的是以''的字符串.
        如果接收消息的应用程序处理了该消息, 它应该返回 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

    )  

     

    学如逆水行舟,不进则退。 博客园技术交流群 群 号:1073255314 (本群没人,刚刚建立 -_-!!! )
  • 相关阅读:
    css 笔记
    解决谷歌浏览器中的input背景色默认是黄色
    lunbo
    操作json进行分组再组
    点击返回顶部
    关于有的手机浏览器下载APK时会成TXT
    火狐浏览器jsonshow插件
    微信web开发者工具
    浏览器UA
    click多次注册事件会导致一个事件被触发多次的解决方法
  • 原文地址:https://www.cnblogs.com/Mj-NaijAm/p/13613301.html
Copyright © 2020-2023  润新知