共享内存用于实现进程间大量的数据传输,共享内存是在内存中单独开辟一段内存空间,这段内存空间有自己特有的数据结构,包括访问权限、大小和最近访问时间等。

1、shmget函数

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);

作用:得到或者创建共享内存

参数:

key:  创建共享内存的标识符,最好用16进制表示。

size:  创建共享内存段的字节数大小。 

flag: 共享内存段的创建标识

  • IPC_CREAT //如果不存在就创建
  • IPC_EXCL //如果存在则返回失败
  • IPC_NOWAIT //如不等待直接返回

返回值:(1)成功,返回共享内存标识符(2)出错,返回-1,错误原因存于errno中。

2、shmat函数

#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);

作用: 将当前进程与共享内存shmid建立链接,shmat返回指定共享内存的映射地址

参数:

shmid:共享内存空间标识符,即ID。

shmaddr:指定共享内存的映射地址。如果为0(NULL),则由系统选择映射的地址,推荐设置为0。如果非0,并且没有指定SHM_RND,则该值即为映射共享内存的地址。

shmflag: 指定共享内存的访问权限和映射条件,一般设置为0,即读写权限。

/* Flags for `shmat'.  */
#define SHM_RDONLY    010000        /* attach read-only else read-write */
#define SHM_RND        020000           /* round attach address to SHMLBA */
#define SHM_REMAP    040000          /* take-over region on attach */
#define SHM_EXEC    0100000           /* execution access */

3、shmdt函数

#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);

作用:shmdt是shmat的反操作,用于将共享内存和当前进程分离。在共享内存使用完毕后都要调用该函数。

参数:shmaddr:指定共享内存的映射地址。

返回值:成功:0,出错:-1,错误原因存在于errno中。

4、shmctl函数

#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

作用:共享内存的内存管理

参数:shmid:共享内存空间标识符,即ID。

cmd:

  • 公共的IPC选项(ipc.h中):
    • IPC_RMID //删除
    • IPC_SET //设置ipc_perm参数
    • IPC_STAT //获取ipc_perm参数
    • IPC_INFO //如ipcs
  • 共享内存自己的选项(shm.h中)【需要root权限】
    • SHM_LOCK //锁定共享内存段
    • SHM_UNLOCK //解锁共享内存段

 buf:共享内存管理结构体。具体说明参见共享内存内核结构定义部分,一般设置为0.

返回值:成功:0,出错:-1,错误原因存在于errno中。

共享内存的代码如下:

#include <iostream>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <thread>
#define SHARE_MEM_SIZE 2048
int main()
{
    int shmid = 0;  //内存标识符

    //创建共享内存
    shmid = shmget((key_t)0x5005,SHARE_MEM_SIZE,0640|IPC_CREAT);
    if(-1 == shmid)
    {
        std::cout << "create shareMem failed." << std::endl;
        return -1;
    }

    char* pMemSharedMem = 0;

    //将当前进程与共享内存shmid建立链接,shmat返回指定共享内存的映射地址
    pMemSharedMem = (char*)shmat(shmid,0,0);
    std::cout << "read context: " << pMemSharedMem << std::endl;


    std::string strContext = "hello world, "+ std::to_string(getpid());
    strncpy(pMemSharedMem,strContext.c_str(),strContext.length());
    std::cout << "write after: " << pMemSharedMem << std::endl;

    //shmat的反操作,将共享内存与当前进程分离
    shmdt(pMemSharedMem);


#if 0
    //操作共享内存, IPC_RMID //删除共享内存,在不使用共享内存的时候进行调用
    if(shmctl(shmid,IPC_RMID,0) == -1)
    {
        std::cout << "delete shared Mem fialed." << std::endl;
        return -1;
    }
#endif
    return 0;
}

第一次运行结果如下:

第二次运行结果如下:

上面的例子存在进程间的同步问题,可以结合信号量的用法来同步进程间的数据操作。

 5、查看创建共享内存命令:ipcs -m

       删除共享内存的命令:ipcrm -m shm_id

具体例子可参考共享内存查看删除等_٩(•̮̮̃•̃)۶的博客-CSDN博客

附加:

共享内存的创建函数也可参考:

共享内存 - shmdt - 《Linux API速查手册》 - 书栈网 · BookStack

Logo

欢迎加入我们的广州开发者社区,与优秀的开发者共同成长!

更多推荐