美文网首页windows进程通信
Windows下实现进程间通信

Windows下实现进程间通信

作者: _NewMoon | 来源:发表于2020-03-11 16:17 被阅读0次

    为了完成本周操作系统的作业,同时也学习一下这块的相关知识,所以写个博客记录下。

    进程与线程

    进程是操作系统中最核心的概念,它是内存中正在运行的程序的一个抽象,我们打开任务管理器:

    任务管理器
    这里运行的程序都是进程,一个进程就是一个正在执行程序的实例(它有输入、输出、程序算法以及状态),我们知道,对于一个应用来说,它可能同时会做很多事,比如在运行一个游戏时,会有键盘鼠标的信息处理以及画面的渲染等等,而线程之间的切换开销是比较大的(需要内核操作),所以,这就需要引入"线程"的概念了,线程是进程中的一个执行单位,一个进程可以含有多个线程,每个线程执行不同的任务在同一个进程中的各个线程,都可以共享该进程所拥有的资源,所以,线程间的通信不需要调动内核,那么线程切换的开销是很小的,线程之间的通信也是很高效的。
    我们可以通过任务管理器查看每个进程的线程,可以看出每个进程下面都有多个线程:
    任务管理器

    简单介绍了进程与线程,再来看看并发与并行:

    并发与并行

    • 1.并发性:指两个或多个事件在同一时间段内间隔发生。
    • 2.并行性:指两个或多个事件在同一时刻发生。

    现代的计算机已经将多个CPU(多核)集成到一个芯片上,但是对于每个CPU来说,一次也只能运行一个程序,所以对于一个CPU来说,从微观上来说,每个进程/线程的执行都是有先后顺序的,但是由于CPU会在这些进程/线程之间来回快速切换,宏观上看,所有的进程/线程都执行了,所以这是一种伪并行(实则是并发),要实现真正的并行,需要硬件的支持,即多个处理器,在同一时间,不同的处理起执行不同的进程/线程。

    windows实现间进程通信

    在网上查阅了相关资料,得知实现进程间通信的方式有很多,比如共享内存,匿名管道与命名管道,消息队列等(代码量都挺大的,而且涵盖很多目前没有学过的东西),所以我选择了一种比较好理解的方式来实现进程间的通信-共享内存

    共享内存:是由一个进程创建的可以被其他进程访问的内存,进程可以直接读写内存,所以是一种高效的IPC方式

    参考博客:点我跳转https://blog.51cto.com/liuker/1654814

    我们需要一个服务端来创建共享内存,然后客户端进程从共享内存中读取数据,从而实现进程间通信。

    服务端

    #include<cstdio>
    #include<cstdlib>
    #include <iostream>
    #include<Windows.h>
    
    #define FileMapping_NAME "Xidian"
    #define  FILESIZE 4096
    LPVOID lpdata = NULL;//指针标识首地址
    
    using namespace std;
    
    int main()
    {
        if (lpdata != NULL){
            cerr<<"Shared memory already exit!"<<endl;
        }
    
        //创建一个有名字标识的共享内存。
        HANDLE hmap =CreateFileMappingA(INVALID_HANDLE_VALUE,
                NULL,
                PAGE_READWRITE | SEC_COMMIT,
                0,
                FILESIZE,
                FileMapping_NAME);
    
        if (hmap == NULL)  //如果句柄指向NULL,表示创建失败
        {
            cerr<<"Create shared memory failed"<<endl;
        }
        else{
            //映射文件到指针
            lpdata = MapViewOfFile(hmap,FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
            if (lpdata == NULL)  //映射失败
            {
                cerr<<"Mapping failed!"<<endl;
            }
            else
            {
                char s[] = "Hello Xidian!";
                memcpy(lpdata, s, sizeof s);  //向这个内存中写入数据
            }
        }
    
        system("pause");
    
        UnmapViewOfFile(lpdata);//解除映射
        CloseHandle(hmap);
    
        system("pause");
        return 0;
    }
    

    客户端:

    #include <cstdio>
    #include <cstdlib>
    #include <Windows.h>
    #include <iostream>
    
    #define FileMapping_NAME "Xidian"
    LPVOID lpdata = NULL;
    
    using namespace std;
    int main()
    {
        //打开一个指定的文件映射对象,获得共享内存对象的句柄
        HANDLE hmapfile =OpenFileMappingA(FILE_MAP_READ, FALSE, FileMapping_NAME);
        if (hmapfile == NULL){
           cerr<<"Open mapfile failed"<<endl;//打开文件映射对象失败
        }
        else
        {
           //将一个文件映射对象映射到当前应用程序的地址空间。
           LPVOID lpbase = MapViewOfFile(hmapfile,FILE_MAP_READ, 0, 0, 0);
           if (lpbase == NULL)
           {
                cerr<<"Mapping failed!"<<endl;
           }
           else
           {
               char *p = (char *)lpbase;
               cout<<p<<endl;
           }
           UnmapViewOfFile(lpbase);//解除映射
           CloseHandle(hmapfile);//一个指定的文件映射对象
    
           system("pause");
        }
        return 0;
    }
    

    流程:
    首先,在服务端即第一个代码中,我们创建一个共享内存,用hmap保存返回的句柄(一个标识符,表示对象或者项目,在windows下用来表示被应用程序所建立或使用的对象的唯一整数),如果共享内存创建成功,将其映射到当前进程的地址空间,这样在服务器进程中我们就可以向内存中写入数据,比如,我们写了一个"Hello Xidian!"的字符串,接下来在客户端中即第二个代码,先打开我们创建好的文件映射对象,再用一个LPVOID(没有类型的指针,通常作为"中间变量")将文件映射对象映射到当前应用程序的地址空间,从这个地址空间中读取数据,观察是否是我们在服务端写的"Hello Xidian!",下面演示一下:

    1.Clion中创建服务端:


    Clion中创建服务端

    2.Codeblocks中运行客户端:


    Codeblocks中运行客户端
    3.结果:
    结果

    4.关闭服务端的程序


    结果

    这样就实现了两个不同进程之间的通信。

    相关文章

      网友评论

        本文标题:Windows下实现进程间通信

        本文链接:https://www.haomeiwen.com/subject/nxlndhtx.html