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

目录

一.概念

二. 特点

三. 步骤

四.函数接口

1.创建key值

2.创建或打开共享内存

3.映射共享内存

4.取消共享

5.删除共享内存


一.概念

        共享内存指的是操作系统在物理内存中申请一块空间,应用程序可以映射到这块空间,进行直接读写操作

二. 特点

        1)  共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝
        2)  为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间
        3)  进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率
        4)  由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等

三. 步骤

1.  创建唯一key值 ftok
2.  创建或打开共享内存 shmget
3.  映射共享内存 shmat
4.  取消映射 shmdt
5.  删除共享内存 shmctl

四.函数接口

1.创建key值

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);
功能:创建key值
参数:pathname:文件名
     proj_id:取整型数的低8位数值
返回值:成功:key值
       失败:-1

 补充:
        key值是根据pathname的inode号和proj_id的低8位组合而成的。如:0x61011944
        pathname只要是路径中存在的文件即可

2.创建或打开共享内存

#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);
功能:创建或打开共享内存
参数:
    key  键值
    size   共享内存的大小
                创建       检测错误
    shmflg   IPC_CREAT|IPC_EXCL|0777  创建共享内存的时候的权限
返回值:成功   shmid  共享内存的id
      出错    -1

查看共享内存命令:ipcs -m

删除共享内存:ipcrm -m shmid

再次执行时会出现报错的情况:
        第一次执行的时候是不是已经创建了这个共享内存,当再一次去执行的时候,肯定会提示文件已存在,共享内存已经存在了

解决方案:

3.映射共享内存

void  *shmat(int  shmid,const  void  *shmaddr,int  shmflg);
功能:映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
参数:
    shmid   共享内存的id号
    shmaddr   一般为NULL,表示由系统自动完成映射
              如果不为NULL,那么有用户指定
    shmflg:SHM_RDONLY就是对该共享内存只进行读操作
                0     可读可写
返回值:成功:完成映射后的地址,
      出错:(void *)-1的地址

4.取消共享

int shmdt(const void *shmaddr);
功能:取消映射
参数:要取消的地址
返回值:成功0  
      失败的-1

5.删除共享内存

int  shmctl(int  shmid,int  cmd,struct  shmid_ds   *buf);
功能:(删除共享内存),对共享内存进行各种操作
参数:
    shmid   共享内存的id号
    cmd     IPC_STAT 获得shmid属性信息,存放在第三参数
            IPC_SET 设置shmid属性信息,要设置的属性放在第三参数
            IPC_RMID:删除共享内存,此时第三个参数为NULL即可    struct  shmid_ds   *buf:是一个结构体指针,但我们是删除共享内存,所以并没有意义,我们直接设置为NULL就可以了
返回:成功0 
     失败-1

操作命令:
        ipcs -m:查看系统中创建的共享内存
        ipcrm -m shmid:删除创建的共享内存

        练习:通过共享内存实现进程间通信,一个进程从终端输入数据,另一个进程打印数据,循环执行,当输入quit时循环结束

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
typedef struct msg
{
    int flag;
    char buf[32];
} *msg_p;
int main(int argc, char const *argv[])
{
    key_t key;
    key = ftok("1.c", 'a');
    if (key < 0)
    {
        printf("ftok err");
        return -1;
    }
    printf("key:%#x\n", key);
    int shmid = shmget(key, 64, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid <= 0)
    {
        if (errno == EEXIST)
        {
            shmid = shmget(key, 64, 0666);
        }
        else
        {
            printf("shmget err\n");
            return -1;
        }
    }
    printf("shmid:%d\n", shmid);
    msg_p p = (msg_p)shmat(shmid, NULL, 0);
    p->flag==1;
    if (p == (msg_p )-1)
    {
        printf("shmat err\n");
        return -1;
    }
    while (1)
    {
        if (p->flag == 1)
        {
            scanf(" %s", p->buf);
            p->flag = 0;
        }
    }
    shmdt(p);
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值