前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux进程通信——共享存储

Linux进程通信——共享存储

作者头像
zy010101
发布2019-08-14 10:50:57
3.9K0
发布2019-08-14 10:50:57
举报
文章被收录于专栏:程序员

共享内存是进程间通信最有用的方式,也是最快的IPC形式。共享内存是说:同一块内存被映射到多个进程的地址空间。但是共享内存并不提供同步机制,因此需要互斥锁或者信号量。使用共享内存唯一需要注意的是:当前如果有进程正在向共享内存写数据,则在写入完成以前,别的进程不应当去读、写共享内存。

共享内存最大的优点就是快。由system V演变而来的内存共享相关函数。目前Linux对system V的共享内存方式支持的比较好。在高版本的Linux内核上,我们有更多的方式来完成共享存储。嵌入式开发板搭载的低版本内核的Linux操作系统基本上都是不支持POSIX标准的内存共享的,只能使用system V的内存共享方式。system V是通过映射特殊文件系统shm中的文件实现内存共享的。通过shmget获得或者创建一个IPC共享内存,并返回这块内存相应的标识符。同时会初始化内核维护的一个数据结构shmid_kernel.当然还会在shm文件系统之中创建一个不属于任何进程的文件。shmid_kernel这个结构体之中的最重要的一个区域是shm_file。它存储被映射文件的地址。

跑题了,本文将介绍mmap存储映射的方式完成的进程间通信。一种方式是使用dev目录下的特殊文件zero。

该文件是一个字符设备文件,该设备是0字节的无限资源。1,5是该设备的主从设备号,不是大小。

zero接收写向他的任何数据,但是会忽略掉这些信息。当对zero进行存储映射的时候,它具备一下性质。

  1. 创建一个未命名的存储区,大小事mmap的第二个参数。
  2. 存储区被初始化为0。
  3. 如果多个进程的公共祖先对mmap指定了MAP_SHARED标志,则这些进程共享此存储区。

一个简单的例子如下。

代码语言:javascript
复制
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    int num = 7777777;
    int fd = open("/dev/zero",O_RDWR);
    if (-1 == fd)
    {
        perror("open zero fail");
        exit(1);
    }
    
    int *p = mmap(0,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if (MAP_FAILED == p)
    {
        perror("mmap fail");
        exit(1);
    }
    close(fd);
    pid_t pid = fork();
    if (0 == pid)
    {
        num = 233;
        *p = 666;
    }
    if (0 < pid)
    {
        wait(NULL);
        printf("*p = %d\n",*p);
        printf("num = %d\n",num);
    }
    if (-1 == pid)
    {
        perror("fork fail");
        exit(1);
    }
    return 0;
}

在子进程中更改了存储映射区域的值为666,也更改了num变量的值。让子进程先运行,父进程后运行,打印输出的结果如下。

对于存储映射区域,父子进程是共享的;对于变量,父子进程是独立的。 使用zero文件的优点是mmap函数的第二个参数len可以指定任意长度,而无需关心zero文件的大小。

Linux除了使用zero以外,它还提供了一种称为匿名映射的方式。这种方式需要在使用mmap的时候指定MAP——ANON标志,并将文件描述符设置为-1。更改上面的程序如下。

代码语言:javascript
复制
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    int num = 7777777;
      
    //注意这行代码和上面程序中的不同之处
    int *p = mmap(0,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANON,-1,0);
  
    if (MAP_FAILED == p)
    {
        perror("mmap fail");
        exit(1);
    }
    //close(fd);
    pid_t pid = fork();
    if (0 == pid)
    {
        num = 233;
        *p = 666;
    }
    if (0 < pid)
    {
        wait(NULL);
        printf("*p = %d\n",*p);
        printf("num = %d\n",num);
    }
    if (-1 == pid)
    {
        perror("fork fail");
        exit(1);
    }
    return 0;
}

运行结果是一致的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年07月31日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档