【Linux共享内存】

Linux共享内存


 


一、基本概念

linux下,每个进程都有自己拥有的内存区域,进程的内存总是私有的。共享内存是从系统的空闲内存池中分配的,希望访问它的每个进程连接它。这个连接过程称为映射。映射后,每个进程都可通过访问自己的内存而访问共享内存区域,从而与其他进程进行通信。
在这里插入图片描述

二、常用函数
 1. shm_open

// 用于创建或者打开共享内存文件,linux系统默认存放目录位/dev/shm
int shm_open(const char *name, int oflag, mode_t mode);

name: 共享文件名
oflag: 打开文件的操作属性,O_CREAT、O_RDWR、O_EXCL的按位或运算组合
mode: 文件共享模式,如0777

返回值: 成功返回fd>0,  失败返回fd<0

2. mmap

// 将打开的文件映射到内存,从而可以用操作内存指针的方式来操作文件数据
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

addr: 要将文件映射到内存中的地址,一般为NULL,由Linux内核来指定
length: 需要映射文件数据的长度
prot: 映射内存区域的操作权限,包括PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE
flags: 标志位参数,包括:MAP_SHARED、MAP_PRIVATE与MAP_ANONYMOUS。 
       MAP_SHARED: 建立共享,用于进程间通信,如果没有这个标志,则别的进程即使能打开文件,也看不到数据。
       MAP_PRIVATE: 只有进程自己用的内存区域
       MAP_ANONYMOUS:匿名映射区
fd: 建立映射区的文件描述符,shm_open或者open打开的文件
offset: 映射文件相对于文件头的偏移位置,应该按4096字节对齐

返回值:成功返回映射的内存地址指针,可以用这个地址指针对映射的文件内容进行读写操作,读写文件数据如同操作内存一样;如果 失败则返回NULL。

3. munmap

// 取消内存映射,将映射的内存从进程地址空间撤销;不调用,在进程终止之前无法释放该内存区域
int munmap(void *addr, size_t length);

addr: 由mmap成功返回的地址
length: 要取消的内存长度

4. shm_unlink

// 删除有shm_open或者open打开的共享文件,在/dev/shm路径下
int shm_unlink(const char *name);

name: 共享文件名

5. ftruncate

// 重置文件大小
int ftruncate(int fd, off_t length);

fd:shm_open返回打开的文件描述符
length:重置大小

三、使用示例

writer.c函数实现,往/dev/shm目录文件写数据

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
 
#define MMAP_DATA_SIZE 1024
 
#define USE_MMAP 1

struct shm_data
{
        int start;
        int end;
        char name[256];
};

 
int main(int argc,char * argv[])
{
        struct shm_data* data;
        int fd = shm_open("shm-file0001", O_CREAT|O_RDWR, 0777);
 
        if (fd < 0) {
                printf("shm_open failed!\n");
                return -1;
        }

        printf("writer fd is %d\n", fd);
 
        ftruncate(fd, MMAP_DATA_SIZE);
        if (USE_MMAP) {
                data = (struct shm_data*)mmap(NULL, sizeof(struct shm_data), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
                if (!data) {
                        printf("mmap failed\n");
                        close(fd);
                }

                printf("writer data addr is %d\n", data);
                printf("before, shm data start is %d\n", data->start);
                data->start = 101;
                data->end = 10000001;
                printf("after, shm start is %d, end is %d\n", data->start, data->end);
                sprintf(data->name, "This is a share memory! %d\n", fd);
 
                munmap(data, MMAP_DATA_SIZE);
        }
        else {
            char buf[1024];
            int len = sprintf(buf,"This is a share memory by write! ! %d\n",fd);
            if (write(fd, buf, len) <= 0) {
                printf("write file %d failed!%d\n",len,errno);
             }  
        }
 
        close(fd);
        getchar();
 
        shm_unlink("shm-file0001");
 
        return 0;
}

 reader.c函数实现,从/dev/shm目录文件写数据

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>


struct shm_data
{
        int start;
        int end;
        char name[256]; 
};
 
#define MMAP_DATA_SIZE 1024
 
int main(int argc,char * argv[])
{
        struct shm_data* data;
        int fd = shm_open("shm-file0001", O_RDWR, 0777);
        if(fd < 0)
        {
                printf("error open shm object\n");
                return -1;
        }
        
        data = (struct shm_data*)mmap(NULL, MMAP_DATA_SIZE, PROT_READ, MAP_SHARED, fd, 0);
        if (!data) {
                printf("mmap failed!\n");
                close(fd);
                return -1;
        }
 
        printf(data->name);
 
        munmap(data,MMAP_DATA_SIZE);
 
        close(fd);
        getchar();
 
        return 0;
}

四、share内存不足解决方法

# 查看大小
df -h /dev/shm

# 系统默认大小修改
sudo vim /etc/fstab
tmpfs /dev/shm tmpfs defaults,size=8192M 0 0

# 刷新/etc/fstab的内容
mount -a 

# 查看挂载点
cat /etc/mtab | grep /dev/shm
mount -l | grep /dev/shm
    
# 临时修改
sudo mount -o remount,size=8192M /dev/shm

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值