共享内存喜欢沙县小吃

news2024/12/22 14:27:12

旭日新摊子好耶!

系统从0开始搭建过通信方案,本地通信方案的代码:System V IPC

里面有共享内存、消息队列、信号量

共享内存

原理

两个进程有自己的内存区域划分,共享内存被创建出的时候是归属操作系统的,还是通过页表来映射以使用物理内存

而用地址空间进行映射让两个进程看到同一份物理内存的方式叫共享内存

所有的操作都是操作系统完成的,但是它并不知道什么时候做(决定通信的是进程)

所以OS必须提供系统调用供进程进行调用,共享内存在系统中可以同时存在多份,供不同个数,不同对进程同时进行通信,共享内存不是简单的一段内存空间,也要有描述并管理共享内存的数据结构和匹配的算法

对共享内存的管理最后要变成对链表的增删查改,共享内存 = 内存空间数据 + 内存属性

代码

怎样创建共享内存呢?

需要看一个函数捏:

第二个参数代表共享内存的大小,第三个参数代表标记位

它本质采取位图的方式传参

标志位:

IPC_CREAT:如果要创建的共享内存不存在,就创建,若存在就获取该共享内存并返回(总能获取一个)

IPC_EXCL:单独使用无意义

IPC_CREAT | IPC_EXCL:如果要创建的共享内存不存在,创建,存在则出错并返回(成功返回的一定是全新的)

有个问题:进程如何知道操作系统是否存在捏?

肯定有标识共享内存唯一性的字段,进程通过唯一性标识符发现

如果让OS自动生成这个标识符是否可行?

不行耶,进程母鸡啊

key由用户形成,只要有唯一性即可

key是用来标识共享内存唯一性的字段,是由用户设计的,有统一标准,就能一个创建,一个获取

由于我们也不知道该设定多少,所以系统为我们提供了一个随机生成key的函数:ftok

于是可以这样设计:

#define __SHM_HPP__
#ifdef __SHM_HPP__

#include<iostream>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<cerrno>
#include<cstdio>
#include<string>

const std::string pathname = "/root/ice/pineapple/shm";
const int proj_id = 0x49;

key_t GetCommKey(const std::string &pathname,int proj_id)
{
    key_t k = ftok(pathname.c_str(),proj_id);
     if(k < 0)
     {
        perror("ftok");
     }
     return k;
}

#endif 

 我们,微笑的弧度一样了!

 shmget的返回值是共享内存的标识符

共享内存不随着进程的结束而释放(一直存在,直到系统重启)

要手动释放,指令或者其他系统调用

文件的生命周期随进程,而共享内存的生命周期随内核

可以这样查共享内存:

ipcs -m

 

想要删除这个共享内存:

ipcrm -m shmid

 那key和shmid有何区别呢?

key是用户形成,内核使用的一个字段,用户不能用key进行shm的管理,是内核进行区分shm唯一性的

而shmid是内核返回给用户的一个标识符,是用来进行用户级对共享内存进行管理的id值

对上面的代码进行封装:

#define __SHM_HPP__
#ifdef __SHM_HPP__

#include<iostream>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<cerrno>
#include<cstdio>
#include<string>

const int gCreater = 1;
const int gUser = 2;
const std::string gpathname = "/root/ice/pineapple/shm";
const int gproj_id = 0x49;
const int gShmSize = 4096;

class Shm
{
private:
key_t GetCommKey()
{
    key_t k = ftok(_pathname.c_str(),_proj_id);
     if(k < 0)
     {
        perror("ftok");
     }
     return k;
}
//创建共享内存
int ShmGet(key_t key,int size,int flag)
{
    int shmid = shmget(key,size,flag);
    if(shmid < 0)
    {
        perror("shmget");
    }
    return shmid;
}
public:
    Shm(const std::string &pathname, int proj_id,int who)
    :_pathname(pathname),_proj_id(proj_id),_who(who)
    {
        _key = GetCommKey();
        if(_who == gCreater) GetShmUserCreate();
        else if(_who == gUser) GetShmForUse();
    }
    ~Shm();

//转十六进制捏
std::string ToHex()
{
    char buffer[128];
    snprintf(buffer,sizeof(buffer),"0x%x",_key);
    return buffer;
}
bool GetShmUserCreate()
{
    if(_who == gCreater)
    {
        _shmid = ShmGet(_key,gShmSize,IPC_CREAT | IPC_EXCL);
        if(_shmid >= 0)
        {
            return true;
        }
    }
    return false;
}
bool GetShmForUse()
{
    if(_who == gUser)
    {
        _shmid = ShmGet(_key,gShmSize,IPC_CREAT);
        if(_shmid >= 0)
        {
            return true;
        }
    }
    return false;
}

private:
    key_t _key;
    int _shmid;
    std::string _pathname;
    int _proj_id;
    int _who;
};

 删除共享内存老是用指令删太挫了,,,看我这招!

了解一下这个: 

 一个命令,标志共享内存删除

加上析构:

#define __SHM_HPP__
#ifdef __SHM_HPP__

#include<iostream>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<cerrno>
#include<cstdio>
#include<string>
#include<unistd.h>

const int gCreater = 1;
const int gUser = 2;
const std::string gpathname = "/root/ice/pineapple/shm";
const int gproj_id = 0x49;
const int gShmSize = 4096;

class Shm
{
private:
key_t GetCommKey()
{
    key_t k = ftok(_pathname.c_str(),_proj_id);
     if(k < 0)
     {
        perror("ftok");
     }
     return k;
}
//创建共享内存
int ShmGet(key_t key,int size,int flag)
{
    int shmid = shmget(key,size,flag);
    if(shmid < 0)
    {
        perror("shmget");
    }
    return shmid;
}
public:
    Shm(const std::string &pathname, int proj_id,int who)
    :_pathname(pathname),_proj_id(proj_id),_who(who)
    {
        _key = GetCommKey();
        if(_who == gCreater) GetShmUserCreate();
        else if(_who == gUser) GetShmForUse();
    }
    ~Shm()
    {
        if(_who == gCreater)
        {
            int res = shmctl(_shmid,IPC_RMID,nullptr);
        }
        std::cout << "shm remove done ..." << std::endl;
    }

//转十六进制捏
std::string ToHex()
{
    char buffer[128];
    snprintf(buffer,sizeof(buffer),"0x%x",_key);
    return buffer;
}
bool GetShmUserCreate()
{
    if(_who == gCreater)
    {
        _shmid = ShmGet(_key,gShmSize,IPC_CREAT | IPC_EXCL);
        if(_shmid >= 0)
        {
            return true;
        }
    }
    return false;
}
bool GetShmForUse()
{
    if(_who == gUser)
    {
        _shmid = ShmGet(_key,gShmSize,IPC_CREAT);
        if(_shmid >= 0)
        {
            return true;
        }
    }
    return false;
}

private:
    key_t _key;
    int _shmid;
    std::string _pathname;
    int _proj_id;
    int _who;
};
#endif 

 要完成剩下的操作,需要挂接一下:

 共享内存滞销,shmat帮帮我们

shmat是将共享内存挂接到地址空间中,shmdt是取消挂接

void *shmat(int shmid,const void *shmaddr,int shmflg); 

 第一个参数是我们申请的共享内存,第二个参数是我们想挂接到哪个地址上,第三个参数指共享内存的访问权限

先写下代码:

Shm.hpp:

#define __SHM_HPP__
#ifdef __SHM_HPP__

#include<iostream>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<cerrno>
#include<cstdio>
#include<string>
#include<unistd.h>

const int gCreater = 1;
const int gUser = 2;
const std::string gpathname = "/root/ice/pineapple/shm";
const int gproj_id = 0x49;
const int gShmSize = 4096;

class Shm
{
private:
key_t GetCommKey()
{
    key_t k = ftok(_pathname.c_str(),_proj_id);
     if(k < 0)
     {
        perror("ftok");
     }
     return k;
}
//创建共享内存
int ShmGet(key_t key,int size,int flag)
{
    int shmid = shmget(key,size,flag);
    if(shmid < 0)
    {
        perror("shmget");
    }
    return shmid;
}
std::string RoleToString(int who)
{
    if(who == gCreater)
    {
        return "Creater";
    }
    else if(who == gUser)
    {
        return "User";
    }
    else
    {
        return "None";
    }
}
public:
    Shm(const std::string &pathname, int proj_id,int who)
    :_pathname(pathname),_proj_id(proj_id),_who(who),_addrshm(nullptr)
    {
        _key = GetCommKey();
        if(_who == gCreater) GetShmUserCreate();
        else if(_who == gUser) GetShmForUse();
        _addrshm = AttachShm();
    }
    ~Shm()
    {
        if(_who == gCreater)
        {
            int res = shmctl(_shmid,IPC_RMID,nullptr);
        }
        std::cout << "shm remove done ..." << std::endl;
    }

//转十六进制捏
std::string ToHex()
{
    char buffer[128];
    snprintf(buffer,sizeof(buffer),"0x%x",_key);
    return buffer;
}
bool GetShmUserCreate()
{
    if(_who == gCreater)
    {
        _shmid = ShmGet(_key,gShmSize,IPC_CREAT | 0666);   //不用IPC_EXCL,避免在已经存在的时候出错
        if(_shmid >= 0)
        {
            return true;
        }
        std::cout << "shm create done..." << std::endl;
    }
    return false;
}
bool GetShmForUse()
{
    if(_who == gUser)
    {
        _shmid = ShmGet(_key,gShmSize,IPC_CREAT);
        if(_shmid >= 0)
        {
            return true;
        }
    }
    return false;
}
void *AttachShm()
{
    if(_addrshm != nullptr)
    {
         DetachShm(_addrshm);
    }
    void *shmaddr = shmat(_shmid,nullptr,0);  
    if(shmaddr == (void*)-1)
    {
        perror("shmat");
    }
    std::cout << "AttachShm " << RoleToString(_who) << std::endl;
    return shmaddr;
}

void DetachShm(void *shmaddr)
{
    if(shmaddr == nullptr)
    {
        return;
    }
    shmdt(shmaddr);
    std::cout << "DetachShm " << RoleToString(_who) << std::endl;
}
void *Addr()
{
    return _addrshm;
}


private:
    key_t _key;
    int _shmid;
    std::string _pathname;
    int _proj_id;
    int _who;
    void *_addrshm;
};

#endif 

server.cc:

#include"Shm.hpp"

int main()
{
    //又是一天,什么都没有改变
    Shm shm(gpathname,gproj_id,gCreater);

    char* shmaddr = (char*)shm.Addr(); 

    while (true)
    {
        std::cout << "shm memory content: " << shmaddr <<std::endl;
        sleep(1);
    }
    
    return 0;
}

 client.cc:

#include"Shm.hpp"

int main()
{
    Shm shm(gpathname,gproj_id,gUser);
   
    char* shmaddr = (char*)shm.Addr(); 

    char ch = 'A';
    while (ch <= 'Z')
    {
        shmaddr[ch - 'A'] = ch;
        ch++;
        sleep(1);
    }
    
    return 0;
}
while :; do ipcs -m;sleep 1;done

perm表示共享内存的权限,所以我们在创建的时候应该指定一下权限

截止目前,我们是否开始通信了呢?

没有啊

我们还没通信过,之前干的都是准备工作啊亲

eeeee哈哈哈哈哈哈

呜呜呜呜

啦啦啦啦啦啦啦啦

我碎掉咯

给自己提个醒,写错过的地方:

我们需要让挂接前共享内存先清空,所以添加个接口(Shm.hpp里面Shm的成员函数)Zero:

void Zero()
{
    if(_addrshm)
    {
        memset(_addrshm,0,gShmSize);
    }
}
#include"Shm.hpp"

int main()
{
    Shm shm(gpathname,gproj_id,gUser);
    shm.Zero();
    char* shmaddr = (char*)shm.Addr(); 

    char ch = 'A';
    while (ch <= 'Z')
    {
        shmaddr[ch - 'A'] = ch;
        ch++;
        sleep(1);
    }
    
    return 0;
}

我现在遇到了一个问题,我刚发现我设置权限为0666了,但是共享内存的权限依旧是0,但这不是最离谱的,最离谱的是我的服务端和我的客户端都可以正常挂接上

 

本着遇到困难睡大觉的原则,我问了chat好几遍,调试信息也多次显示创建出的权限就是0,我真的不知道我哪里错了,所以决定在这里粘个源代码供后人嘲笑(相当于权限都是0,但是所有人可读可写可访问):

Shm.hpp:

#define __SHM_HPP__
#ifdef __SHM_HPP__

#include<iostream>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<cerrno>
#include<cstdio>
#include<cstring>
#include<string>
#include<unistd.h>

const int gCreater = 1;
const int gUser = 2;
const std::string gpathname = "/root/ice/pineapple/shm";
const int gproj_id = 0x49;
const int gShmSize = 4096;

class Shm
{
private:
key_t GetCommKey()
{
    key_t k = ftok(_pathname.c_str(),_proj_id);
     if(k < 0)
     {
        perror("ftok");
     }
     return k;
}
//创建共享内存
// int ShmGet(key_t key,int size,int flag)
// {
//     int shmid = shmget(key,size,flag);
//     if(shmid < 0)
//     {
//         perror("shmget");
//     }
//     return shmid;
// }
std::string RoleToString(int who)
{
    if(who == gCreater)
    {
        return "Creater";
    }
    else if(who == gUser)
    {
        return "User";
    }
    else
    {
        return "None";
    }
}
public:
    Shm(const std::string &pathname, int proj_id,int who)
    :_pathname(pathname),_proj_id(proj_id),_who(who),_addrshm(nullptr)
    {
        _key = GetCommKey();
        if(_who == gCreater) GetShmUserCreate();
        else if(_who == gUser) GetShmForUse();
        _addrshm = AttachShm();
    }
    ~Shm()
    {
        if(_who == gCreater)
        {
            int res = shmctl(_shmid,IPC_RMID,nullptr);
        }
        std::cout << "shm remove done ..." << std::endl;
    }

//转十六进制捏
std::string ToHex()
{
    char buffer[128];
    snprintf(buffer,sizeof(buffer),"0x%x",_key);
    return buffer;
}
bool GetShmUserCreate()
{
    if(_who == gCreater)
    {
        _shmid = shmget(_key,gShmSize,IPC_CREAT | 0666);   //不用IPC_EXCL,避免在已经存在的时候出错
        //调试代码,我看看权限是什么,会不会是显示的问题
        struct shmid_ds shm_info;
        if (shmctl(_shmid, IPC_STAT, &shm_info) == -1) 
        {
            perror("shmctl IPC_STAT");
        } 
        else 
        {
            std::cout << "Created Shm Permissions: " << std::oct << shm_info.shm_perm.mode << std::endl;
        }
        if(_shmid >= 0)
        {
            return true;
        }
        std::cout << "shm create done..." << std::endl;
    }
    return false;
}
bool GetShmForUse()
{
    if(_who == gUser)
    {
        _shmid = shmget(_key,gShmSize,IPC_CREAT | 0666);    //哈哈,真是令人忍俊不禁
        struct shmid_ds shm_info;
        
        //调试代码,我看看权限是什么,会不会是显示的问题
        if (shmctl(_shmid, IPC_STAT, &shm_info) == -1) 
        {
            perror("shmctl IPC_STAT");
        } 
        else 
        {
            std::cout << "Created Shm Permissions: " << std::oct << shm_info.shm_perm.mode << std::endl;
        }
        
        if(_shmid >= 0)
        {
            return true;
        }
    }
    return false;
}

// // 更改共享内存权限,我先注释掉
// void SetShmPermissions(int shmid, mode_t perms)
// {
//     struct shmid_ds shm_info;
//     if (shmctl(shmid, IPC_STAT, &shm_info) == -1)
//     {
//         perror("shmctl IPC_STAT");
//         return;
//     }

//     shm_info.shm_perm.mode = perms;
//     if (shmctl(shmid, IPC_SET, &shm_info) == -1)
//     {
//         perror("shmctl IPC_SET");
//     }
// }

void *AttachShm()
{
    if(_addrshm != nullptr)
    {
         DetachShm(_addrshm);
    }
    void *shmaddr = shmat(_shmid,nullptr,0);  
    if(shmaddr == (void*)-1)
    {
        perror("shmat");
    }
    std::cout << "AttachShm " << RoleToString(_who) << std::endl;
    return shmaddr;
}

void DetachShm(void *shmaddr)
{
    if(shmaddr == nullptr)
    {
        return;
    }
    shmdt(shmaddr);
    std::cout << "DetachShm " << RoleToString(_who) << std::endl;
}

void Zero()
{
    if(_addrshm)
    {
        memset(_addrshm,0,gShmSize);
    }
}

void *Addr()
{
    return _addrshm;
}


private:
    key_t _key;
    int _shmid;
    std::string _pathname;
    int _proj_id;
    int _who;
    void *_addrshm;
};

#endif 

Server.cc:

#include"Shm.hpp"

int main()
{
    //又是一天,什么都没有改变
    Shm shm(gpathname,gproj_id,gCreater);

    char* shmaddr = (char*)shm.Addr(); 

    while (true)
    {
        std::cout << "shm memory content: " << shmaddr <<std::endl;
        sleep(1);
    }
    
    return 0;
}

Client.cc: 

#include"Shm.hpp"

int main()
{
    Shm shm(gpathname,gproj_id,gUser);
    char* shmaddr = (char*)shm.Addr(); 

    char ch = 'A';
    while (ch <= 'Z')
    {
        shmaddr[ch - 'A'] = ch;
        ch++;
        sleep(1);
    }
    
    return 0;
}

这是一些报错信息:

《这确实是不寻常的》 

要爱自己,不要为难自己 

共享内存不提供对共享内存的任意保护机制,会造成数据不一致的问题

这是缺点

我们在访问共享内存的时候,没有使用系统调用

共享内存是所有进程IPC速度最快的,因为共享内存大大的减少了数据的拷贝次数

我们可以基于管道对双方进行保护:

namedPiped.hpp

#pragma once

#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<cerrno>
#include<cstdio>
#include<unistd.h>
#include<string>
#include<fcntl.h>

#define DefaultFd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
#define BaseSize 4096

const std::string comm_path = "./myfifo";

class NamePiped
{
private:
    //打开文件的模式
    bool OpenNamedPipe(int mode)
    {
        _fd = open(_fifo_path.c_str(),mode);
        if(_fd < 0)
        {
            return 0;
        }
        return true;
    }
public:
    NamePiped(const std::string &path,int who)
    :_fifo_path(path), _id(who),_fd(DefaultFd)
    {
        if(_id == Creater)
        {
            int res = mkfifo(path.c_str(),0666);
            if(res != 0)
            {
              perror("mkfifo");
            }
        }
    }
    bool OpenForRead()
    {
        return OpenNamedPipe(Read);
    }
    bool OpenForWrite()
    {
        return OpenNamedPipe(Write);
    }
    
    //输出:const &:const std::string &XXX
    //输入:*      std::string *
    //输入输出:&   std::string &

    int ReadNamedPipe(std::string *out)
    {
        char buffer[BaseSize];
        int n = read(_fd,buffer,sizeof(buffer));
        if(n > 0)
        {
            //读取成功
            buffer[n] = 0;
            *out = buffer;
        }
        return n;
    }
    int WriteNamedPipe(const std::string &in)
    {
        return write(_fd,in.c_str(),in.size());
        
    }
    ~NamePiped()
    {
        if(_id == Creater)
        {
            int res = unlink(_fifo_path.c_str());
            if(res != 0)
            {
                perror("unlink");
            }
        }
        if(_fd != DefaultFd)
        {
            close(_fd);
        }
    }
private:
    const std::string _fifo_path;
    int _id;
    int _fd;
};

 Shm.hpp

#define __SHM_HPP__
#ifdef __SHM_HPP__

#include<iostream>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<cerrno>
#include<cstdio>
#include<cstring>
#include<string>
#include<unistd.h>

const int gCreater = 1;
const int gUser = 2;
const std::string gpathname = "/root/ice/pineapple/shm";
const int gproj_id = 0x49;
const int gShmSize = 4096;

class Shm
{
private:
key_t GetCommKey()
{
    key_t k = ftok(_pathname.c_str(),_proj_id);
     if(k < 0)
     {
        perror("ftok");
     }
     return k;
}
//创建共享内存
// int ShmGet(key_t key,int size,int flag)
// {
//     int shmid = shmget(key,size,flag);
//     if(shmid < 0)
//     {
//         perror("shmget");
//     }
//     return shmid;
// }
std::string RoleToString(int who)
{
    if(who == gCreater)
    {
        return "Creater";
    }
    else if(who == gUser)
    {
        return "User";
    }
    else
    {
        return "None";
    }
}
public:
    Shm(const std::string &pathname, int proj_id,int who)
    :_pathname(pathname),_proj_id(proj_id),_who(who),_addrshm(nullptr)
    {
        _key = GetCommKey();
        if(_who == gCreater) GetShmUserCreate();
        else if(_who == gUser) GetShmForUse();
        _addrshm = AttachShm();
    }
    ~Shm()
    {
        if(_who == gCreater)
        {
            int res = shmctl(_shmid,IPC_RMID,nullptr);
        }
        std::cout << "shm remove done ..." << std::endl;
    }

//转十六进制捏
std::string ToHex()
{
    char buffer[128];
    snprintf(buffer,sizeof(buffer),"0x%x",_key);
    return buffer;
}
bool GetShmUserCreate()
{
    if(_who == gCreater)
    {
        _shmid = shmget(_key,gShmSize,IPC_CREAT | 0666);   //不用IPC_EXCL,避免在已经存在的时候出错
        //调试代码,我看看权限是什么,会不会是显示的问题
        struct shmid_ds shm_info;
        if (shmctl(_shmid, IPC_STAT, &shm_info) == -1) 
        {
            perror("shmctl IPC_STAT");
        } 
        else 
        {
            std::cout << "Created Shm Permissions: " << std::oct << shm_info.shm_perm.mode << std::endl;
        }
        if(_shmid >= 0)
        {
            return true;
        }
        std::cout << "shm create done..." << std::endl;
    }
    return false;
}
bool GetShmForUse()
{
    if(_who == gUser)
    {
        _shmid = shmget(_key,gShmSize,IPC_CREAT | 0666);    //哈哈,真是令人忍俊不禁
        struct shmid_ds shm_info;
        
        //调试代码,我看看权限是什么,会不会是显示的问题
        if (shmctl(_shmid, IPC_STAT, &shm_info) == -1) 
        {
            perror("shmctl IPC_STAT");
        } 
        else 
        {
            std::cout << "Created Shm Permissions: " << std::oct << shm_info.shm_perm.mode << std::endl;
        }
        
        if(_shmid >= 0)
        {
            return true;
        }
    }
    return false;
}

// // 更改共享内存权限,我先注释掉
// void SetShmPermissions(int shmid, mode_t perms)
// {
//     struct shmid_ds shm_info;
//     if (shmctl(shmid, IPC_STAT, &shm_info) == -1)
//     {
//         perror("shmctl IPC_STAT");
//         return;
//     }

//     shm_info.shm_perm.mode = perms;
//     if (shmctl(shmid, IPC_SET, &shm_info) == -1)
//     {
//         perror("shmctl IPC_SET");
//     }
// }

void *AttachShm()
{
    if(_addrshm != nullptr)
    {
         DetachShm(_addrshm);
    }
    void *shmaddr = shmat(_shmid,nullptr,0);  
    if(shmaddr == (void*)-1)
    {
        perror("shmat");
    }
    std::cout << "AttachShm " << RoleToString(_who) << std::endl;
    return shmaddr;
}

void DetachShm(void *shmaddr)
{
    if(shmaddr == nullptr)
    {
        return;
    }
    shmdt(shmaddr);
    std::cout << "DetachShm " << RoleToString(_who) << std::endl;
}

void Zero()
{
    if(_addrshm)
    {
        memset(_addrshm,0,gShmSize);
    }
}

void *Addr()
{
    return _addrshm;
}


private:
    key_t _key;
    int _shmid;
    std::string _pathname;
    int _proj_id;
    int _who;
    void *_addrshm;
};

#endif 

 client.cc

#include"Shm.hpp"
#include"namedPiped.hpp"

int main()
{
    //创建共享内存
    Shm shm(gpathname,gproj_id,gUser);
    char* shmaddr = (char*)shm.Addr(); 

    //打开管道
    NamePiped fifo(comm_path,User);
    fifo.OpenForWrite();

    char ch = 'A';
    while (ch <= 'Z')
    {
        shmaddr[ch - 'A'] = ch;
        ch++;
        std::string temp = "wakeup";
        std::cout << "add" << ch << "into Shm, " << "wakeup reader" << std::endl;

        fifo.WriteNamedPipe(temp);

        sleep(1);
    }
    
    return 0;
}

 server.cc

#include"Shm.hpp"
#include"namedPiped.hpp"

int main()
{
    //又是一天,什么都没有改变
    //创建共享内存
    Shm shm(gpathname,gproj_id,gCreater);
    char* shmaddr = (char*)shm.Addr(); 

    //创建管道
    NamePiped fifo(comm_path,Creater);
    fifo.OpenForRead();

    

    while (true)
    {
        std::string temp;
        fifo.ReadNamedPipe(&temp);
        
        std::cout << "shm memory content: " << shmaddr <<std::endl;
        sleep(1);
    }
    
    return 0;
}

 

 

 共享内存的设置最好设置成4096的整数倍,如果多一点点会浪费

因为操作系统只会给你分配4096的整数倍的共享内存

怎样获取共享内存的属性捏?

 

void DebugShm()
{
    struct  shmid_ds ds;
    int n = shmctl(_shmid,IPC_STAT,&ds);
    if(n < 0)
    {
        return;
    }
    std::cout << "ds.shm_perm.__key: " << ToHex(ds.shm_perm.__key) << std::endl;
    std::cout << "ds.shm_nattch: " << ds.shm_nattch << std::endl;
}

 

 System V消息队列

原理

操作系统申请个队列,现在有两个进程:进程A+进程B,进程A可以使用消息队列的调用接口,向消息队列中放数据块,消息队列是一个进程向另一个进程发送数据块的方式,操作系统也要先描述在组织,所以不仅要有消息队列,还要有相应的属性数据

接口

那有哪些接口呢,让我们康康

int msgget(key_t key,int msgflg);

 这个接口是在获取消息队列

key_t fork(const char *pathname,int proj_id);

消息队列使用的时候和共享内存差不多,不想用了的话就可以用msgctl捏

int msgctl(int msqid,int cmd,struct msqid_ds *buf);

我们消息队列也有自己的属性捏

 

消息队列是收发结点,共享内存是挂接

 发消息捏:

int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);

收消息捏:

ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg);

 

 使用消息队列需要我们自定义一个结构体,msgbuf

struct msgbuf
{
    long mtype;        /*message type,must be > 0 */
    char mtext[1];     /*message data */
};

这个大小是自己定义的捏

发消息是这样的捏:

#define A 1
#define B 2
struct msgbuf message;
message.mtype = B;
message.mtext = ("hello world");
msgsnd(msgid,&message,sizeof(message),0);

 收消息则可以这样干:

#define A 1
#define B 2
struct msgbuf recvbuffer;
msgrcv(msgid,&recvbuffer,sizeof(recvbuffer),A,0);
msgrcv(msgid,&recvbuffer,sizeof(recvbuffer),B,0);
指令操作

生命周期是随内核的鹅,可以这样查看消息队列:

ipcs -q

 

 删除的话就是:

ipcrm -q msqid

距离永远不会成为阻碍

 

毛豆好可爱

 

 

很好笑,下了拜拜

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2114666.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32G474内部温度传感器的使用

目录 概述 1 认识STM32G474内部温度传感器 1.1 温度传感器概述 1.2 温度传感器实现原理 1.3 读取温度方法 1.4 ADC模块上温度sensor的位置框图 2 STM32Cube创建项目 2.1 配置参数 2.2 STM32Cube生成的软件架构 3 温度数据算法实现 3.1 算法介绍 3.2 源代码 概述…

【H2O2|全栈】关于HTML(1)认识HTML

HTML相关知识 目录 前言 准备工作 WEB前端是什么&#xff1f; HTML是什么&#xff1f; 如何运行HTML文件&#xff1f; 标签 概念 分类 双标签和单标签 行内标签和块标签 HTML文档结构 预告和回顾 UI设计相关 Markdown | Md文档相关 项目合作管理相关 后话 前…

顶踩Emlog插件源码

源码介绍 顶踩Emlog插件源码 前些天看到小刀娱乐网的文章页面有了一些变化&#xff0c;那就是增加了一个有价值/无价值的顶踩按钮。 样式也是非常的好看 再加上两个表情包是非常的有趣。 写到了Emlog系统&#xff0c;效果如上图。 如何使用&#xff1a; 需要在echo_log.…

Python 算法交易实验88 QTV200日常推进-关于继续前进的思考

说明 念念不忘,必有回响 最初的时候&#xff0c;完全不了解架构方面的东西。后来决定要搞好这一块的时候&#xff0c;也就是不断的琢磨&#xff0c;到现在4年的时间&#xff0c;改变已经非常大了。现在习以为常的&#xff0c;都是当初梦寐以求的&#xff0c;而且在可见的未来 &…

论文精读-Supervised Raw Video Denoising with a Benchmark Dataset on Dynamic Scenes

论文精读-Supervised Raw Video Denoising with a Benchmark Dataset on Dynamic Scenes 优势 1、构建了一个用于监督原始视频去噪的基准数据集。为了多次捕捉瞬间&#xff0c;我们手动为对象s创建运动。在高ISO模式下捕获每一时刻的噪声帧&#xff0c;并通过对多个噪声帧进行…

龙芯+FreeRTOS+LVGL实战笔记(新)——05部署主按钮

本专栏是笔者另一个专栏《龙芯+RT-Thread+LVGL实战笔记》的姊妹篇,主要的区别在于实时操作系统的不同,章节的安排和任务的推进保持一致,并对源码做了改进和优化,各位可以先到本人主页下去浏览另一专栏的博客列表(目前已撰写36篇,图1所示),再决定是否订阅。此外,也可以…

行空板上YOLO和Mediapipe图片物体检测的测试

Introduction 经过前面三篇教程帖子&#xff08;yolov8n在行空板上的运行&#xff08;中文&#xff09;&#xff0c;yolov10n在行空板上的运行&#xff08;中文&#xff09;&#xff0c;Mediapipe在行空板上的运行&#xff08;中文&#xff09;&#xff09;的介绍&#xff0c;…

Node.js学习记录(一)

目录 一、文件读取 readFile 二、写入文件 writeFile 三、动态路径 __dirname:表示当前文件所处的目录、path.join 四、获取路径文件名 path.basename 五、提取某文件中的css、JS、html 六、http 七、启动创建web服务器 服务器响应 八、将资源请求的 url 地址映射为文…

idea插件开发的第二天-写一个时间查看器

介绍 Demo说明 本文基于maven项目开发,idea版本为2022.3以上,jdk为1.8本文在Tools插件之上进行开发 Tools插件说明 Tools插件是一个Idea插件,此插件提供统一Spi规范,极大的降低了idea插件的开发难度,并提供开发者模块,可以极大的为开发者开发此插件提供便利Tools插件安装需…

Spark的Web界面

http://localhost:4040/jobs/ 在顶部导航栏上&#xff0c;可以点击以下选项来查看不同类型的Spark应用信息&#xff1a; Jobs - 此视图将列出所有已提交的作业&#xff0c;并提供每个作业的详细信息&#xff0c;如作业ID、名称、开始时间、结束时间等。Stages - 此视图可以查…

新160个crackme - 050-daxxor

运行分析 需要破解Name和Serial PE分析 C程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida找到关键字符串&#xff0c;双击进入函数 通过静态分析发现&#xff1a;1、Name通过计算得到Name12、对Name1第3、5、6分别插入byte_401290、byte_401290、word_401292&…

Weibull概率分布纸(EXCEL VBA实现)

在学习Weibull分布理论的时候&#xff0c;希望有一张Weibull概率纸&#xff0c;用来学习图解法。但是在度娘上没有找到的Weibull概率纸的电子版。在书上看到的Weibull概率纸&#xff0c;只能复印下来使用。于是萌生了自己制作Weibull概率纸的想法&#xff0c;帮助自己更好地学习…

综合案例-数据可视化-折线图

一、json数据格式 1.1 json数据格式的定义与功能 json是一种轻量级的数据交互格式&#xff0c;可以按照json指定的格式去组织和封装数据&#xff0c;json数据格式本质上是一个带有特定格式的字符串。 功能&#xff1a;json就是一种在各个编程语言中流通的数据格式&#xff0…

全倒装COB超微小间距LED显示屏的工艺技术,相比SMD小间距有何优势

全倒装COB&#xff08;Chip On Board&#xff09;超微小间距LED显示屏&#xff0c;在工艺技术上的革新&#xff0c;相较于传统的SMD&#xff08;Surface Mount Device&#xff09;小间距LED显示屏&#xff0c;展现出了多方面的显著优势。 首先&#xff0c;全倒装技术极大地提升…

JAVAEE初阶第七节(下)——物理原理与TCP_IP

系列文章目录 JAVAEE初阶第七节&#xff08;下&#xff09;——物理原理与TCP_IP 文章目录 系列文章目录JAVAEE初阶第七节&#xff08;下&#xff09;——物理原理与TCP_IP 一.网络层重点协议 1. IP协议如何管理地址 1.1 解决IP地址不够用的问题 1.2 网段划分 1.3 特殊的IP…

深度剖析AI情感陪伴类产品及典型应用 Character.ai

前段时间AI圈内C.AI的受够风波可谓是让大家都丈二摸不着头脑&#xff0c;连C.AI这种行业top应用都要找谋生方法了&#xff01;投资人摸不着头脑&#xff0c;用户们更摸不着头脑。在这之前断断续续玩了一下这款产品&#xff0c;这次也是乘着这个风波&#xff0c;除了了解一下为什…

【数据库】MySQL表的Updata(更新)和Delete(删除)操作

目录 1.Update 案例1&#xff1a;将孙悟空同学的数学成绩变更为 80 分 案例2&#xff1a;将曹孟德同学的数学成绩变更为 60 分&#xff0c;语文成绩变更为 70 分 案例3&#xff1a;将总成绩倒数前三的 3 位同学的数学成绩加上 30 分 案例4&#xff1a;将所有同学的语文成绩…

计算机网络与Internet应用

一、计算机网络 1.计算机网络的定义 网络定义&#xff1a;计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享…

『功能项目』武器的切换实例【34】

本章项目成果展示 我们打开上一篇33战士的A键连击的项目&#xff0c; 本章要做的事情是按键盘E键切换职业时切换手中的武器 首先在资源商店下载免费的武器模型 创建一个空物体 命名为WeaponPos 将武器预制体拖拽至WeaponPos &#xff08;注意调整空物体位置就可以后续文章会更…

CSP-J 之C++常用英文缩写

文章目录 C常用英文缩写前言常用缩写解析C 基础缩写输入输出相关控制台 命名与类型常用函数在线测评相关 总结 C常用英文缩写 前言 在编程比赛和日常开发中&#xff0c;C是一门广泛使用的编程语言&#xff0c;许多英文缩写贯穿其中。了解这些缩写不仅有助于提高编程效率&…