自学内容网 自学内容网

C++ Linux IPC进程通信-共享内存

原文链接:C++ Linux IPC进程通信-共享内存

共享内存<sys/shm.h>

库函数

// 创建共享内存
int shmget(key_t key, size_t size, int shmflg); 
    return 共享内存的ID(成功) -1(错误)
    key为一个标记内存的关键字,可用自己指定,也可以用ftok函数转文件名为key,
    shmflg标志包括IPC_CREAT(创建)|IPC_EXCL(存在则报错)|SHM_RDONLY(只读)|SHM_RND(附加到指定地址的最接近的可用地址)|SHM_NORESERVE(不预留共享内存资源)

    !!:注意IPC命名对象需要指定该对象的文件权限如IPC_CREAT|0666

// 分配空间并连接
void *shmat(int shm_id, const void *shm_addr, int shmflg); 
    return 分配空间首地址 或 -1
   shm_id为返回的id shm_addr为nullptr自动分配,否则就近分配  shmflg可为SHM_RDONLY(只读)|SHM_NORESERVE(不预留共享内存资源)

// 删除连接(不删除空间)
int shmdt(const void *shmaddr);  shmaddr为首地址
    return 成功0,出错-1

//控制
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
    return 成功0,出错-1
    cmd:IPC_STAT(读出数据到buf),IPC_SET(写入),IPC_RMID(删除共享内存)

该控制命令实际上就是通过更新结构体来控制共享内存配置,如分配大小或其他的
struct shmid_ds { 
    uid_t shm_perm.uid; 
    uid_t shm_perm.gid; 
    mode_t shm_perm.mode; 
    //其他配置
};

使用memcpy实现数据的移动

实例:使用信号量+共享内存实现变量自增

#include <iostream>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <fcntl.h>
#include <semaphore.h>
#include <unistd.h>
#include <string.h>
using namespace std;

class Cnt{
public:
    int c; //需要共享
    string s; //不需要共享
    Cnt():c(0),s(""){};
    ~Cnt(){};
};
template <typename T>
void check(const char* er, const T& a, const T& b) {
    if (a == b) {
        perror(er);
        exit(EXIT_FAILURE);
    }
}

void run(Cnt &cnt,sem_t *nsem,void *addr,int size){
    for(int i=0;i<3;i++){
        sem_wait(nsem);
        memcpy(&(cnt.c),addr,size);
        cnt.c++;
        cout<<cnt.c<<"\n";
        memcpy(addr,&(cnt.c),size);
        sem_post(nsem);
    }
}

int main()
{
    Cnt cnt;
    int size= sizeof(cnt.c);
    
    sem_t* nsem=sem_open("name_sem",O_CREAT,0666,1); 
    check(string("sem_open").c_str(),nsem,SEM_FAILED);
    int fd=open("./shm",O_CREAT|O_RDWR,0666);
    check(string("open").c_str(),fd,-1);
    check(string("close").c_str(),close(fd),-1);
    key_t k=ftok("./shm",'A');
    check(string("ftok").c_str(),k,-1);
    int sid=shmget(k,size,IPC_CREAT|0666); 
    check(string("shmget").c_str(),sid,-1);
    void *addr = shmat(sid,nullptr,0);
    check(string("shmat").c_str(),addr,(void*)-1);
    
    pid_t cid=fork();
    if(cid==-1){
        perror("fork");
        exit(EXIT_FAILURE);
    }else if(cid>0){
        run(cnt,nsem,addr,size);
    }else{
        run(cnt,nsem,addr,size);
    }
    
    if(cid>0){
        check(string("shmdt").c_str(),shmdt(addr),-1);
        check(string("shmctl").c_str(),shmctl(sid,IPC_RMID,nullptr),-1);
        check(string("sem_close").c_str(),sem_close(nsem),-1);
        check(string("sem_unlink").c_str(),sem_unlink("name_sem"),-1);
    }
    
    return 0;
}

特点

优点

优点速度快,大量数据操作下效率高,直接对内存操作.

缺点

需要其他的方法实现同步支持,并且对内存管理和分配有要求


原文地址:https://blog.csdn.net/qq_58539881/article/details/142317256

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!