共享内存详解

共享内存

共享内存是一种允许多个进程或线程访问同一块内存区域的机制,它是最快的可用进程间通信(IPC)形式之一。

共享内存的特点

  • 快速性:由于多个进程或线程直接访问同一块内存区域,因此数据交换和通信的速度非常快,远超过其他IPC机制(如命名管道、消息队列等)。
  • 高效性:共享内存减少了数据的冗余拷贝,降低了内存消耗,提高了系统的整体效率。
  • 灵活性:共享内存可以与其他通信机制(如信号量)结合使用,以实现进程间的同步和互斥,从而满足复杂的通信需求。

 


shmget函数 

功能:用于创建贡献内存(如果创建成功,一定是一个新的共享内存)

参数:

  •  key:这个共享内存的名字(共享内存在内核中的唯一性标识)
  • size:这个共享内存大小
  • shmflg:有九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样

IPC_CREAT:如果存在,直接获取它。如果不存在,就创建它

IPC_CREAT | IPC_EXCL 如果不存在创建它。如果存在,出错返回 

返回值: 成功返回一个非负整数,即该共享内存的标识码,失败返回-1。

 ftok函数

功能:ftok函数是一个在Unix和Linux系统中广泛使用的函数,用于生成一个唯一的键(key),这个键通常用于IPC(进程间通信)机制,如消息队列、信号量或共享内存。ftok的名字来源于“file to key”的缩写,意味着它可以根据文件生成一个键。

 参数:

  • pathname:指向文件路径的指针,这个文件通常是项目中的一个已知文件。这个路径不需要指向一个实际存在的文件,但必须是唯一的,以便在不同的项目或实例中生成不同的键。
  • proj_id:一个8位(1字节)的整数,通常用于进一步区分同一路径下的不同键。

 返回值:如果成功,ftok函数返回一个唯一的键(key_t类型)。如果失败,返回-1,并设置errno以指示错误。

 shmat函数

功能:将共享内存连接到进程地址空间中

 参数:

  • shmid:共享内存的标识
  • shamaddr:指定连接的地址
  • shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY

shmaddr为NULL,内核自动选择一个地址

shmaddr不为NULL而且shmflg无SHM_RND标识,则以shmaddr为连接地址

shmaddr不为NULL而且shmflg设置SHM_RND标识,则连接地址会自动向下调整为SHMLBA的整数倍。(shmaddr-(shmaddr%SHMLBA))

shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

 返回值:成功返回一个指针,指向共享内存的第一节,失败返回-1。

shmdt函数

功能:将共享内存和当前线程脱离

参数: 

  •  shmaddr:之前调用shmat返回的指针

返回值:成功返回0,失败返回-1

一个进程打开文件,进程退出时,这个被打开的文件就会被系统自动释放掉(文件的生命周期随进程)

共享内存被创建,如果进程结束,我们没有主动释放,则内存会一直存在,除非重启系统(共享内存生命周期随内核)

shmctl函数 

功能:用于控制共享内存

参数:

  • shmid:由shmget返回的共享内存标识码
  • cmd:将要采取的动作(有三个取值)
  • buf:指向一个保存着共享内存的模式状态和访问权限的数据结构

返回值:成功返回0,失败返回-1


 代码实操

comm.cc

#pragma once

#include <stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include <unistd.h>

#define PATHNAME "."
#define PROJ_ID 0x6666
client.cc
#include"comm.h"

int main()
{

    key_t key = ftok(PATHNAME,PROJ_ID);
    if(key<0)
    {
        perror("ftok error");
        return(-1);
    }

    int shmid = shmget(key,4096,IPC_CREAT|IPC_EXCL|0666);
    if(shmid<0)
    {
        perror("shmget error");
        return(-2);
    }
    
    char* addr = (char*)shmat(shmid,nullptr,0);
    sleep(1);

    for(int i=0;i<26;i++)
    {
        addr[i] = 'A' + i;
        addr[i+1] = '\0';
        sleep(1);
    }

    shmdt(addr);

    int n = shmctl(shmid,IPC_RMID,NULL);
    if(n<0)
    {
        perror("shmctl error");
        return(-3);
    }


    return 0;
}
server.cc
#include"comm.h"

int main()
{

    key_t key = ftok(PATHNAME,PROJ_ID);
    if(key<0)
    {
        perror("ftok error");
        return(-1);
    }

    int shmid = shmget(key,4096,IPC_CREAT);
    if(shmid<0)
    {
        perror("shmget error");
        return(-2);
    }
    
    char* addr = (char*)shmat(shmid,nullptr,0);
    sleep(1);

    for(int i=0;i<26;i++)
    {
        printf("read#: %s\n",addr);
        sleep(1);
    }

    shmdt(addr);

    int n = shmctl(shmid,IPC_RMID,NULL);
    if(n<0)
    {
        perror("shmctl error");
        return(-3);
    }


    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值