Linux-共享内存

这篇具有很好参考价值的文章主要介绍了Linux-共享内存。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言


在这之前我们已经学习了两种进程间通信方式:匿名管道和命名管道。
从我们之前的学习已经知道,想让多个进程间进行通信就需要让他们一起看到同一份资源。
匿名管道是通过fork子进程来让子进程继承父进程的fd。
命名管道是通过生成命名管道文件,并一起打开管道文件。

一、system V共享内存

共享内存相对于我们之前的管道通信有一定区别:

1.共享内存是要让多个进程看到同一份内存.

根据之前我们介绍过的冯洛伊曼体系,对于内存级别的通信特性就代表了共享内存其通信效率要高于管道通信!

2.进程想要看到同一份共享内存,需要key

Linux-共享内存,Linux系统编程,linux,运维,服务器
这里生成的key方式与哈希字符串类似,通过算法来形成key。所以要想要形成同样的key,就必须确保pathname和porj_id相同,不同进程凭借同样的key来访问同一份共享内存!

申请共享内存

Linux-共享内存,Linux系统编程,linux,运维,服务器
参数key 代表如果要访问该共享内存需要的key。
参数size代表申请的共享内存大小,这里需要注意的是,共享内存的大小是以4096个字节为单位,所以size最好是4096的倍数。
参数shmflg是模式选项,有 IPC_CREAT 和 IPC_EXCL , IPC_CREAT单独使用代表 如果没有该共享内存则创建,有则使用已经存在的。 IPC_EXCL单独使用没有意义,如果和IPC_CREAT一起使用代表如果没有该共享内存则创建,如果已经存在则报错。
返回值是共享内存的id,就跟文件一样,我们的共享内存也需要进行管理,所以就也有id。

挂载共享内存

由于我们的共享内存的通信方式是让多个进程看到同一份内存,从我们之前学习地址空间的知识,进程需要通过虚拟地址空间->页表->物理内存,所以,要想看到看到位于物理内存的共享内存,就需要修改页表来做到,所以提供了挂载共享内存的接口函数
Linux-共享内存,Linux系统编程,linux,运维,服务器
参数shmid是我们刚刚讲的共享内存id。
参数shmaddr 可以指定shmaddr的地址为挂载的共享内存地址,一般设置为nullptr。
参数shmflg是模式选项,SHM_RND和SHM_RDONLY,SHM_RND与shmaddr相关,SHM_RDONLY指定该进程只允许对共享内存进行读操作。
返回值为挂载的共享内存地址。

删除共享内存挂载

注意:这里是删除挂载,不是删除共享内存!!!

Linux-共享内存,Linux系统编程,linux,运维,服务器
参数shmaddr为共享内存在该进程的地址。
返回值若为1则删除成功,-1则发生错误。

删除共享内存

Linux-共享内存,Linux系统编程,linux,运维,服务器
参数shmid为共享内存id。
参数cmd为模式选项,其中IPC_RMID为删除选项
参数buf这里暂时不讨论。
返回值若为1则删除成功,-1则发生错误

我们要想删除共享内存也不止这一种方式

通过输入ipcs -m 查看存在的共享内存属性
Linux-共享内存,Linux系统编程,linux,运维,服务器

通过输入ipcrm -m shmid 来删除共享内存

二、示例代码

#Server端
#include "comm.hpp"
#include "Log.hpp"

int main()
{
    // 1.创建创建token
    key_t key = ftok(PATH_NAME, PROJ_ID);
    Log(Debug) << "共享秘钥创建成功! step 1"
               << " [key:" << getKey(key) << "]" << std::endl;


    // 2.申请共享内存
    int shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
    if (shmid == -1)
    {
        Log(Error) << "共享内存创建失败!!!!! step 2" << std::endl;

        perror("shmget");
        exit(1);
    }
    Log(Debug) << "共享内存创建成功! step 2" << std::endl;

    //sleep(10);

    char *shmaddr = (char *)shmat(shmid, nullptr, SHM_RDONLY);
    if ((void *)shmaddr == (void *)-1)
    {
        Log(Error) << "共享内存挂载失败!!!!!! step 3" << std::endl;

        perror("shmat");
        exit(2);
    }
    Log(Debug) << "共享内存挂载成功! step 3" << std::endl;

   // sleep(5);



    //开始访问共享内存
    while(1)
    {
        printf("%s\n",shmaddr);
        sleep(1);
        if(strcmp(shmaddr,"quit") == 0) break;
    }


    int n = shmdt(shmaddr);
    if (n == -1)
    {
        Log(Error) << "共享内存挂载删除失败! step 4" << std::endl;

        perror("shmdt");
        exit(3);
    }

    Log(Debug) << "共享内存挂载删除! step 4" << std::endl;

    //sleep(5);

    n = shmctl(shmid, IPC_RMID, nullptr);
    if (n == -1)
    {
        Log(Error) << "共享内存删除失败! step 5" << std::endl;

        perror("shmctl");
        exit(4);
    }
    Log(Debug) << "共享内存删除成功! step 5" << std::endl;

    return 0;
}
#Client端
#include "Log.hpp"
#include "comm.hpp"

int main()
{
    key_t key = ftok(PATH_NAME, PROJ_ID);
    Log(Debug) << "共享秘钥创建成功!step 1"
               << " [key:" << getKey(key) << "]" << std::endl;

    int shmid = shmget(key, SHM_SIZE, 0);
    if (shmid == -1)
    {
        Log(Error) << "共享内存获取失败!!!!! step 2" << std::endl;
        perror("shmget");
        exit(1);
    }
    Log(Debug) << "共享内存获取成功!step 2" << std::endl;

    //sleep(10);


    char *shmaddr = (char *)shmat(shmid, nullptr, 0);
    if ((void *)shmaddr == (void *)-1)
    {
        Log(Error) << "共享内存挂载失败!!!!!! step 3" << std::endl;   

        perror("shmat");
        exit(2);
    }
    Log(Debug) << "共享内存挂载成功!step 3" << std::endl;

    //sleep(5);

    while(1)
    {
        //std::cout << "请输入:->" ;
        ssize_t n = read(0, shmaddr, SHM_SIZE - 1);
        if(n > 0)
        {
            shmaddr[n - 1] = 0;
            if(strcmp(shmaddr,"quit") == 0) break;
        }
    }



    int n = shmdt(shmaddr);
    if (n == -1)
    {
        Log(Error) << "共享内存挂载删除失败! step 4" << std::endl;

        perror("shmdt");
        exit(3);
    }

    Log(Debug) << "共享内存挂载删除!step 4" << std::endl;

    //sleep(5);

    return 0;
}
comm.hpp
#include <iostream>
#include <cstdio>
#include <sys/types.h>
#include <sys/ipc.h>
#include <assert.h>
#include <sys/shm.h>
#include <unistd.h>
#include <cstring>
#define PROJ_ID 10086
#define SHM_SIZE 4096

char buffer[514] = {0};

const char *getKey(key_t key)
{

    sprintf(buffer, "0x%x", key);
    return buffer;
}


#define PATH_NAME "/home/fengjunzi/test"
Log.hpp
#include <iostream>
#include <time.h>
#include <string>

#define Debug 0
#define Error 1

const std::string com[] = {
    "Debug",
    "Error"};

std::ostream &Log(int command)
{
    std::cout << "[" << (unsigned)time(nullptr) << "]:"
              << "[" << com[command] << "]" <
        " ";
    return std::cout;
}

三.运行效果

Linux-共享内存,Linux系统编程,linux,运维,服务器
它的缺陷从运行就可以看出来,共享内存没有进行同步与互斥。
不能像管道一样具有访问控制,就会出现写端只写了一半,但是读端已经开始读了的情况。文章来源地址https://www.toymoban.com/news/detail-823405.html

到了这里,关于Linux-共享内存的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Linux高并发服务器开发---笔记1(环境搭建、系统编程、多进程)

    Linux高并发服务器开发---笔记1(环境搭建、系统编程、多进程)

    0613 首先这整个系列笔记属于笔记①:牛客校招冲刺集训营—C++工程师中的 第四章 笔记。 视频课链接: 视频1:Linux高并发服务器开发(40h); 视频2:第4章 项目制作与技能提升(录播)(26h30min); 视频课3: 第5章 高频考点与真题精讲(录播)中的 5.10-5.13 项目回顾 有个学

    2024年02月15日
    浏览(60)
  • Linux系统编程,使用C语言实现简单的FTP(服务器/客户端)

    Linux系统编程,使用C语言实现简单的FTP(服务器/客户端)

    前言 跟着上官社长 陈哥花了一个月的时间终于把Linux系统编程学的差不多了,这一个月真的是头疼啊,各种bug,调的真心心累,不过好在问题都解决掉了,在此也感谢一下答疑老师,给我提供了很多的思路,本文章是对前段时间学习Linux,做一个小小的总结,才疏学浅,只学

    2024年02月12日
    浏览(12)
  • 运维 | 查看 Linux 服务器 IP 地址

    大多数在操作 Linux 系统时,我们经常需要知道服务器的 IP 比便于后续的一系列操作,这时候有快速查看主机 IP 的命令行操作,能够有效的帮助我们 本章节主要记录一些常用查看服务器 IP 的命令,希望对大家有所帮助。 查看 Linux 服务器的 IP 地址的命令大体上有以下几种。

    2024年04月27日
    浏览(50)
  • 【运维】Linux 跨服务器复制文件文件夹

    如果是云服务 建议用内网ip scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时,用scp可以帮你把文件移出来

    2024年02月08日
    浏览(52)
  • Linux - 进阶 NFS服务器 详解网络共享服务器 ( 预备知识)

               N  :  就是 网络 Network          F   :     就是  File  文件         S   :  system          简称为 网络文件系统                 官方   :               NFS 是一种古老的用于UNIX/LINUX主机之间进行文件共享的协议              Network  File  System 网

    2024年02月13日
    浏览(9)
  • 简单对已有云服务器进行linux环境搭建以及共享服务器

    简单对已有云服务器进行linux环境搭建以及共享服务器

    外壳程序:Xshell7 云服务器:华为云 服务器操作系统:centos7 区域尽量选择距离所处地距离自己最近的区域。 镜像这里选择的为centos7.6-7.9,最好不要超过8 ,8的生态环境较差且已经停止更新和维护了,7完全够用。 进入所买服务器网站,找到所买的服务器实例, 重新设置密码。

    2024年03月22日
    浏览(17)
  • 【Linux网络服务】Centos7搭建nfs文件共享服务器

    【Linux网络服务】Centos7搭建nfs文件共享服务器

    1.NFS介绍 2.环境准备 3.在A服务端机器安装nfs-utils和rpcbind包 4.启动rpcbind检查是否启动了rpcbind服务并监听111端口 5.配置NFS服务的配置文件,参数配置:vi /etc/exports 数据同步与数据异步的区别 数据同步:当系统从内存中向磁盘中持久化数据时,同步发送表示只有当内存中的数据

    2024年02月06日
    浏览(18)
  • Linux服务器配置指南:网络、用户管理、共享服务及DNS配置详解

    💂 个人网站:【 海拥】【神级代码资源网站】【办公神器】 🤟 基于Web端打造的:👉轻量化工具创作平台 💅 想寻找共同学习交流的小伙伴,请点击【全栈技术交流群】 设置虚拟机的网卡为仅主机模式,并要求服务器采用双网卡, ens33 IP地址设置为192.168. 5.x/24(其中x学号),

    2024年02月05日
    浏览(16)
  • 【Linux 服务器运维】定时任务 crontab 详解 | 文末送书

    【Linux 服务器运维】定时任务 crontab 详解 | 文末送书

    本文思维导图概述的主要内容: 1.1 什么是 crontab Crontab 是一个在 Unix 和 Linux 操作系统上 用于定时执行任务 的工具。它允许用户创建和管理计划任务,以便在特定的时间间隔或时间点自动运行命令或脚本。Crontab 是 cron table 的缩写, cron 指的是 Unix 系统中的一个后台进程,它

    2024年02月08日
    浏览(69)
  • Linux服务器增加虚拟交换内存

    Linux服务器增加虚拟交换内存

    使用dd命令创建名为swapfile 的swap交换文件(文件名和目录任意): dev/zero是Linux的一种特殊字符设备(输入设备),可以用来创建一个指定长度用于初始化的空文件,如临时交换文件,该设备无穷尽地提供0,可以提供任何你需要的数目。 bs=1024 :单位数据块(block)同时读入/输出

    2024年02月15日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包