LINUX进程间的通信--共享内存

一、概念

共享内存(Shared Memory)就是允许多个进程访问同一个内存空间,是在多个进程之间共享和传递数据最高效的方式。操作系统将不同进程之间共享内存安排为同一段物理内存,进程可以将共享内存连接到它们自己的地址空间中,如果某个进程修改了共享内存中的数据,其它的进程读到的数据也将会改变。

二、相关函数

1.int shmget(key_t key, size_t size, int shmflg);

功能: 用来获取或创建共享内存
参数:
key IPC_PRIVATE(key值会是0)  ftok(key值不会是0) 的返回值
size 共享内存区大小
shmflg open 函数的权限位,也可以用 8 进制表示法
返回值:
成功:共享内存段标识符 ‐‐‐ID‐‐‐ 文件描述符
出错: ‐1
示例:
#include<stdio.h>
#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
	int shmID;

	shmID = shmget(IPC_PRIVATE,128,0777);
	if(shmID == -1)
	{
		printf("共享内存创建失败\n");
		return -1;
	}
	else
	{
		printf("共享内存创建成功,ID号%d\n",shmID);
		system("ipcs -m");//查看共享内存信息
	}
	return 0;
}

运行结果:

PS:创建内存时,只会创建内核中的共享内存,并不会产生应用层的映射内存。调用映射地址函数时才会产生映射地址,这样进程之间的数据传输就不需要在内核进行操作,就可以在内核映射出来的地址进行数据传输操作。

2.void *shmat(int shm_id, const void *shm_addr, int shmflg);

功能: 把共享内存连接映射到当前进程的地址空间
参数:
shm_id:ID
shm_addr: 映射到的地址, NULL 为系统自动完成的映射
shmflg
        SHM_RDONLY共享内存只读
        默认是0 ,表示共享内存可读写
返回值:
成功:映射后的地址
失败: NULL
示例:
#include<stdio.h>
#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
        int shmID;
        key_t key;
        char *p;
        key = ftok("a.c",1);
        if(key == -1)
                printf("key fail!\n");
        else
                printf("key value %x\n",key);
        shmID = shmget(key,128,IPC_CREAT|0777);
        if(shmID == -1)
        {
                printf("共享内存创建失败\n");
                return -1;
        }
        else
        {
                printf("共享内存创建成功,ID号%d\n",shmID);
                system("ipcs -m");//查看共享内存信息
        }

        p = (char *)shmat(shmID, NULL, 0);
        printf("映射的地址是%p",p);
        printf("请输入数据:");
        fgets(p,128,stdin);

        printf("共享内存的数据是%s\n",p);
        return 0;
}
运行结果:

3.int shmdt(const void *shmaddr);

功能: 将进程里的地址映射删除
参数:
shmid 要操作的共享内存标识符
返回值:
成功: 0
出错: ‐1
#include<stdio.h>
#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
        int shmID;
        key_t key;
        char *p;
        key = ftok("a.c",1);
        if(key == -1)
                printf("key fail!\n");
        else
                printf("key value %x\n",key);
        shmID = shmget(key,128,IPC_CREAT|0777);
        if(shmID == -1)
        {
                printf("共享内存创建失败\n");
                return -1;
        }
        else
        {
                printf("共享内存创建成功,ID号%d\n",shmID);
                system("ipcs -m");//查看共享内存信息
        }

        p = (char *)shmat(shmID, NULL, 0);
        printf("映射的地址是%p",p);
        printf("请输入数据:");
        fgets(p,128,stdin);
        printf("共享内存的数据是%s\n",p);
        int add = shmdt(p);//删除映射内存
        if(add == 0)
                printf("删除映射内存成功\n");
        p = 0;
        printf("删除共享内存过后的地址%p\n",p);

        return 0;
}

4.int shmctl(int shm_id, int command, struct shmid_ds *buf);

功能: 删除共享内存对象
参数:
shmid 要操作的共享内存标识符
cmd
        IPC_STAT (获取对象属性 )‐‐‐ 实现了命令 ipcs ‐m
        IPC_SET (设置对象属性 )
        IPC_RMID (删除对象 ) ‐‐‐ 实现了命令 ipcrm ‐m
buf 指定 IPC_STAT/IPC_SET 时用以保存 / 设置属性
返回值:
成功: 0
出错: ‐1
示例:
#include<stdio.h>
#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
        int shmID;
        key_t key;
        char *p;
        key = ftok("a.c",1);
        if(key == -1)
                printf("key fail!\n");
        else
                printf("key value %x\n",key);
        shmID = shmget(key,128,IPC_CREAT|0777);
        if(shmID == -1)
        {
                printf("共享内存创建失败\n");
                return -1;
        }
        else
        {
                printf("共享内存创建成功,ID号%d\n",shmID);
                system("ipcs -m");//查看共享内存信息
        }

        p = (char *)shmat(shmID, NULL, 0);
        printf("映射的地址是%p",p);
        printf("请输入数据:");
        fgets(p,128,stdin);
        printf("共享内存的数据是%s\n",p);
        int add = shmdt(p);//删除映射内存
        if(add == 0)
                printf("删除映射内存成功\n");
        p = 0;
        printf("删除共享内存过后的地址%p\n",p);

        shmctl(shmID,IPC_RMID,NULL);//删除共享内存对象

        system("ipcs -m");

        return 0;
}

运行结果:

进程间的通信示例:

shm_write.c:

#include<stdio.h>
#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
        int shmID;
        key_t key;
        char *p;
        key = ftok("a.c",1);
        if(key == -1)
                printf("key fail!\n");
        else
                printf("key value %x\n",key);
        shmID = shmget(key,128,IPC_CREAT|0777);
        if(shmID == -1)
        {
                printf("共享内存创建失败\n");
                return -1;
        }
        else
        {
                printf("共享内存创建成功,ID号%d\n",shmID);
                system("ipcs -m");//查看共享内存信息
        }

        p = (char *)shmat(shmID, NULL, 0);
        printf("映射的地址是%p",p);
        printf("请输入数据:");
        fgets(p,128,stdin);
        system("ipcs -m");

        return 0;
}

shm_read.c:

#include<stdio.h>
#include<stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
        int shmID;
        key_t key;
        char *p;
        key = ftok("a.c",1);
        if(key == -1)
                printf("key fail!\n");
        else
                printf("key value %x\n",key);
        shmID = shmget(key,128,0777);
        if(shmID == -1)
        {
                printf("共享内存创建失败\n");
                return -1;
        }
        else
        {
                printf("共享内存创建成功,ID号%d\n",shmID);
                system("ipcs -m");//查看共享内存信息
        }

        p = (char *)shmat(shmID, NULL, 0);
        printf("映射的地址是%p\n",p);
        printf("共享内存的数据是%s\n",p);
        int add = shmdt(p);//删除映射内存
        if(add == 0)
                printf("删除映射内存成功\n");
        p = 0;
        printf("删除共享内存过后的地址%p\n",p);

        shmctl(shmID,IPC_RMID,NULL);//删除共享内存对象

        system("ipcs -m");

        return 0;
}
~ 

三、特点

1. 共享内存创建之后,一直存在于内核中, 直到被删除或系统关闭
2. 共享内存和管道不一样,读取后, 内容仍然在共享内存中
  • 19
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值