IPC通信方式之共享内存

共享内存的使用步骤 server端和client端
server端:
1.获取key值 --> ftok
2.创建共享内存 --> shmget flags==IPC_CREAT | IPC_EXCL
3.进程和共享内存进行挂接(关联) --> shmat
void *shmat(int shmid, const void *shmaddr, int shmflg); --> shmflg设为0表示默认为可读可写
4.使用共享内存进行通信
5.进程和共享内存进行取消关联 --> shmdt
6.删除共享内存 --> shmctl

client端:
1.获取key值
2.获取server端创建的共享内存 --> shmget flags==IPC_CREAT
3.进程和共享内存进行挂接(关联) --> shmat
4.使用共享内存进行通信
5.进程和共享内存取消关联 --> shmdt

查看IPC方式的通信资源
1.ipcs -m --> 查看共享内存
2.ipcs -q --> 查看消息队列
3.ipcs -s --> 查看信号量

ipcrm -m 指定shmid 删除一个共享内存
所有System V系列的IPC通信方式比如共享内存,信号量,消息队列,他们的生命周期不随进程的结束而结束,是随操作系统的。如果需要删除,必须手动删除
System V系列的通信方式都是作用于同一台主机上的不同进程
POSIX 系列的通信方式可以作用于不同主机上的不同进程


共享内促你的大小一般建议设置为4KB的整数倍-->因为操作系统分配共享内存的大小时是以4KB为基本单位的

//comm.hpp
#ifndef __COMM_HPP

#include <iostream>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define __COMM_HPP

#endif

#define PATHNAME "/tmp"
#define PROJID 1
#define MAX_SIZE 4096

key_t getKey()
{
    key_t key = ftok(PATHNAME, PROJID);
    if (key == -1)
    {
        std::cout << "getKey()" << errno << ":" << strerror(errno);
        exit(1);
    }
    return key;
}

int createShm(key_t key)
{
    int shmid = shmget(key, MAX_SIZE, IPC_CREAT | IPC_EXCL | 0600);
    if (shmid == -1)
    {
        std::cout << "createShm" << errno << ":" << strerror(errno);
        exit(2);
    }
    return shmid;
}

int getShm(key_t key)
{
    int shmid = shmget(key, MAX_SIZE, IPC_CREAT);
    if (shmid == -1)
    {
        std::cout << "getShm" << errno << ":" << strerror(errno);
        exit(2);
    }
    return shmid;
}

void *connectShm(int shmid)
{
    void *start = shmat(shmid, nullptr, 0);
    if ((long long)start == -1L)
    {
        std::cout << "connectShm" << errno << ":" << strerror(errno);
        exit(3);
    }
    return start;
}

void disconnectShm(const void *start)
{
    int ret = shmdt(start);
    if (ret == -1)
    {
        std::cout << "disconnectShm" << errno << ":" << strerror(errno);
        exit(4);
    }
}

void destroyShm(int shmid)
{
    int ret = shmctl(shmid, IPC_RMID, nullptr);
    if (ret == -1)
    {
        std::cout << "destroyShm" << errno << ":" << strerror(errno);
    }
}

//shm.client.cc
#include "comm.hpp"


int main(){
    //获取key值
    key_t key = getKey();

    //获取共享内存
    int shmid = getShm(key);

    printf("key:%x,shmid:%d\n",key,shmid);

    //和共享内存建立挂接
    char* start = (char*)connectShm(shmid);

    //使用共享内存进行通信
    int cnt = 0;
    while(1){
        const char* buf = "hello server,我是客户端,我在给你发消息";
        snprintf(start,MAX_SIZE,"[第%d次消息]:%s",++cnt,buf);
        sleep(1);
    }
    //和共享内存取消挂接
    disconnectShm(start);

    //进程退出
    return 0;
}
//shm.server.cc
#include "comm.hpp"


int main(){
    //获取key值
    key_t key = getKey();

    //创建共享内存
    int shmid = createShm(key);
    printf("key:%x,shmid:%d\n",key,shmid);

    //和共享内存挂接
    char* start = (char*)connectShm(shmid);

    //使用共享内存进行通信
    while(1){
        std::cout << "#client->server" << start << std::endl;
        sleep(1);
    }

    //和共享内存取消挂接
    disconnectShm(start);

    //删除共享内存
    destroyShm(shmid);
    return 0;
}
//makefile
.PHONY:all
all:shm_server shm_client
shm_server:shm_server.cc
	g++ -o $@ $^ -std=c++11
shm_client:shm_client.cc
	g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
	rm -f shm_server shm_client

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值