共享内存.

文章详细介绍了Linux系统中如何使用共享内存进行进程间通信,包括shmget创建或打开共享内存,shmat映射共享内存,shmdt解除映射,以及shmctl删除共享内存。同时,提到了共享内存的特性,如高速传输效率和无内置同步机制,以及使用示例。
摘要由CSDN通过智能技术生成

1.共享内存

1.1含义

两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新。

1.2工作流程

用户空间到内存—写;内存到用户空间—读。

1.3特性

(1)数据传输效率快,适用于对数据的速率、数量要求较高的场合(如果要求不高,一般使用消息队列).

(2)共享内存具有内存的通用特性,对共享内存执行写操作时以覆盖的方式写入,对共享内存读取数据后,内存中的数据保留,不会删除。

(3)内核中的内存是不具有共享机制的,在使用共享内存前需要先创建一块共享内存(物理内存)。

(4)共享内存并未提供同步机制,在一个进程结束对共享内存的写操作之前,不可以使用另外一个进程开始对它进行读取。

2.共享内存相关函数

2.1 shmget(创建或打开共享内存)

函数头文件:#include <sys/ipc.h>

#include <sys/shm.h>

函数原型: intshmget(key_t key, size_t size, int shmflg);

函数功能:在内存上创建一块共享内存空间;

函数参数:

key_t key:键值 父子进程亲缘进程之间键值可以是0x000000私有IPC_PRIVATE(#defineIPC_PRIVATE ((__kernel_key_t) 0) )

size_t size:大小创建共享内存空间大小;

int shmflg:标志(如:IPC_CREAT |操作权限)

IPC_CREAT:创建

IPC_EXCL与IPC_CREAT:如果已存在共享内存返回错误,如果未存在则创建共享内存;

系统调用: SYSCALL_DEFINE3(shmget,key_t, key, size_t, size, int, shmflg) -> ipcget

返回值:成功返回共享内存编号,失败返回-1;

备注:如果在父子进程之间(具有亲缘关系的进程间的使用)使用共享内存,Key键值可以为“0”或“IPC_PRIVATE”。两个任意进程之间使用共享内存,Key键值可以直接填写一个非0的整数或通过ftok 让系统分配一个Key键值。并且共享内存不同于有名管道,有名管道的同一根管道只能被创建一次,而共享内存则可以创建多次(几个进程使用共享内存,就需要分别在几个进程中创建,并且保证通信的进程使用的KEY值一致)。而在父子进程中,只需在创建进程之前创建一次共享内存即可。

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

int main(int argc,char *argv[])
{
    int shmid = shmget(0x88888,512,IPC_CREAT|0644);
    if(shmid == -1)
    {
        perror("shmget");
        exit(1);
    }
    printf("共享内存ID:%d\n",shmid);
    return 0;
}

2.2 shmat(映射共享内存)

映射:将共享内存映射到进程中的内存空间;

为了方便用户空间对内存的操作,使用地址映射的方式;

函数shmat用于将共享内存段映射到进程空间的某一地址;

意义:反应速度快,操作方便。

函数头文件:#include <sys/types.h>

#include <sys/shm.h>

函数原型:void *shmat(int shmid, const void *shmaddr, int shmflg);

函数功能:把共享映射到进程空间(建立共享内存与当前的进程的映射关系)。

函数参数:

int shmid:共享内存的ID号,能够确定计算机中唯一的共享内存块;

const void *shmaddr:如果此参数为NULL系统会自动分配未使用的地址;(常用)

int shmflg:标志

SHM_RDONLY只读

可读可写为0

返回值:void *:成功时映射后的首地址,失败时返回-1。

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

int main(int argc,char *argv[])
{
    int shmid = shmget(0x88888,512,IPC_CREAT|0644);
    if(shmid == -1)
    {
        perror("shmget");
        exit(1);
    }
    printf("共享内存ID:%d\n",shmid);
    //进行映射
    int * p = shmat(shmid,NULL,0);
    //进行映射
    int * q = shmat(shmid,NULL,0);
    //读写操作
    *p =10;
    printf("%d\n",*q);
    //字符串
    char * p1 = shmat(shmid,NULL,0);
    char * q1 = shmat(shmid,NULL,0);
    //写
    strcpy(p1,"hello");
    //读
    printf("%s\n",q1);
    return 0;
}

2.3 解除映射

函数头文件:#include <sys/types.h>

#include <sys/shm.h>

函数原型:int shmdt(const void *shmaddr);

函数功能:撤销当前的进程与共享内存之间的映射关系。

函数形参:

const void *shmaddr:进程空间映射后到地址(shmat函数的返回值)。

函数返回值:int:成功返回0,失败返回-1。

2.4 删除共享内存

函数头文件:#include <sys/ipc.h>

#include <sys/shm.h>

函数原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);

函数功能:控制共享内存具体操作。

函数形参:

int shmid:共享内存的id(shmget函数的返回值)。

int cmd:共享内存控制命令。

IPC_STAT:查看共享内存的特性。

IPC_SET:设置共享内存的特性。

IPC_RMID:删除共享内存。

struct shmid_ds *buf:共享内存特性结构体(命令附带参数),不需要则指定为NULL。

函数返回值:int:成功返回0,失败返回-1。

备注:如果需要删除共享内存,必须保证共享内存的所有连接全部断开(取消映射)后才能被真正删除。

映射共享内存

2.5 应用

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

int main(int argc,char *argv[])
{
    int shmid = shmget(0x088888,512,IPC_CREAT|0644);
    if(shmid == -1)
    {
        perror("shmget");
        exit(1);
    }
    printf("共享内存ID:%d\n",shmid);
    if(strcmp(argv[1],"w")==0)
    {
        //字符串
        char * p1 = shmat(shmid,NULL,0);
        for(int i = 0; ;i++)
        {
            //写
            char buff[512]={0};
            sprintf(buff,"%04d",i);
            strcpy(p1,buff);
            sleep(1);
        }
        shmdt(p1);
    }
    else if(strcmp(argv[1],"r")==0)
    {
        char * q1 = shmat(shmid,NULL,0);
        while(1)
        {
            printf("%s\n",q1);
        }
        shmdt(q1);
    }
    shmctl(shmid,IPC_RMID, NULL);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值