System V|共享内存基本通信框架搭建|【超详细的代码解释和注释】

55b442c530014f30b6a3b4eda19d23ec.png

 


前言

那么这里博主先安利一下一些干货满满的专栏啦!

手撕数据结构https://blog.csdn.net/yu_cblog/category_11490888.html?spm=1001.2014.3001.5482这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏https://blog.csdn.net/yu_cblog/category_11464817.html这里是STL源码剖析专栏,这个专栏将会持续更新STL各种容器的模拟实现。

STL源码剖析https://blog.csdn.net/yu_cblog/category_11983210.html?spm=1001.2014.3001.5482


什么是System V的共享内存

进程间通信本质:让不同进程看到同一份资源

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

当我们用管道进行进程间通信的时候,我们知道,无论是匿名管道的形式还是命名管道的形式,最后都是需要在磁盘上创建部分空间的。

而共享内存的方案,只需要在内存的级别上创建共享的空间!

02e64df334f04d408603eb90060342f2.png

至于详细的系统调用接口,博主会在代码的注释中进行解释。

今天博主带着大家把框架搭好,关于通信的具体实现,博主会在下一期进行详细的讲解!


代码下载地址 

Git地址https://github.com/Yufccode/BitCode/tree/main/Linux/%E4%BB%A3%E7%A0%81/1126_SystemV%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98%E6%A1%86%E6%9E%B6%E6%90%AD%E5%BB%BA


 部分实现原理

9a36e3a23e544a32b771e1064b2c6098.png9f07e20119cf4915a225d4b3c39ef59c.png 41d6034a0e6d40828950a47237b57177.png9dee891625e0436090362a22a31233b2.png4566e7cc304045ebb76a56c18087b075.png 


shmServer.cc和shmClient.cc代码 

注意,仅有这两份代码是不够用的,需要下载代码学习的伙伴要在博主上面提供的链接上下载代码。

这里面是一个完整的项目!

shmServer.cc


#include "comm.hpp"

// 为了让key更好看,和命令行输出的对应起来
// 写一个转换成16进制的函数
std::string TransToHex(key_t k)
{
    char buffer[32];
    snprintf(buffer, sizeof buffer, "0x%x", k);
    return buffer;
}

int main()
{
    // 1.创建公共的key值
    key_t k = ftok(PATH_NAME, PROJ_ID);
    assert(k != -1);
    Log("create key done", Debug) << " server key: " << TransToHex(k) << std::endl;

    // 2.创建共享内存 -- 建议创建一个全新的共享内存 -- Server是通信的发起者
    int shmid = shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid == -1)
    {
        // 创建失败
        perror("shmget");
        exit(1);
    }
    Log("create shm done", Debug) << " shmid: " << shmid << std::endl;

    //3.将制定的共享内存,挂接到自己的地址空间
    sleep(3);
    char* shmaddr = (char*)shmat(shmid,nullptr,0);
    Log("attach shm done", Debug) << " shmid: " << shmid << std::endl;
    sleep(3);
    //我们会看到 挂接数会从0变成1!

    // ================= 这里面就是通信的逻辑了!================= //
    //...

    // ================= 这里面就是通信的逻辑了!================= //

    //4.解除挂接
    //  将制定的共享内存,从自己的地址空间中去关联
    int n = shmdt(shmaddr);
    assert(n!=-1);
    (void)n;
    Log("detach shm done", Debug) << " shmid: " << shmid << std::endl;
    sleep(3);


    // last. 删除共享内存
    //IPC_RMID表示,即便是有进程和当下的shm挂接,依旧删除共享内存
    int n = shmctl(shmid, IPC_RMID, nullptr);
    assert(n != -1);
    (void)n;
    Log("delete shm done", Debug) << " shmid: " << shmid << std::endl;
    return 0;
}

 shmClient.cc


#include "comm.hpp"

int main()
{
    key_t k = ftok(PATH_NAME, PROJ_ID);
    if(k<0)
    {
        Log("create key failed", Error) << " client key: " << k << std::endl;
        exit(1);
    }
    Log("create key done", Debug) << " client key: " << k << std::endl;
    //获取共享内存
    int shmid = shmget(k,SHM_SIZE,IPC_CREAT);
    if(shmid<0)
    {
        Log("create shm success", Error) << " client key: " << k << std::endl;
        exit(2);
    }
    Log("create shm failed", Debug) << " client key: " << k << std::endl;
    sleep(5);
    //
    char* shmaddr = (char*)shmat(shmid,nullptr,0);
    if(shmaddr ==nullptr)
    {
        Log("attach shm failed", Error) << " client key: " << k << std::endl;
        exit(3);
    }
    Log("attach shm success", Debug) << " client key: " << k << std::endl;
    sleep(5);


    //使用


    //去关联
    int n = shmdt(shmaddr);
    assert(n!=-1);
    Log("detach shm success", Debug) << " client key: " << k << std::endl;
    sleep(5);

    //client要不要chmctl删除呢?不需要!!!
    
    return 0;
}

尾声

看到这里,相信大家对System V通信结构的基本搭建已经有了一定的理解了!如果大家觉得这篇文章对你们有帮助的话,不要吝啬你们的点赞收藏哦!

 

posted @ 2023-02-26 23:37  背包Yu  阅读(22)  评论(0编辑  收藏  举报  来源