Linux进程通信——system V进程间通信

news2024/11/26 22:20:05

目录

system V共享内存

共享内存的原理

共享内存的建立与释放

共享内存的创建 

shmget

 共享内存的释放

shmctl

共享内存的关联

shmat

共享内存的去关联 

shmdt

 用共享内存实现serve和client的简单通信


共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到 内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据

system V共享内存

共享内存的原理

共享内存让不同进程看到同一份资源的方式就是,在物理内存当中申请一块内存空间,然后将这块内存空间分别与各个进程各自的页表之间建立映射,再在虚拟地址空间当中开辟空间并将虚拟地址填充到各自页表的对应位置,使得虚拟地址和物理地址之间建立起对应关系,至此这些进程便看到了同一份物理内存,这块物理内存就叫做共享内存。

一般通过共享内存通信分为三个步骤

1.创建共享内存

2.关联进程和取消关联

3.释放贡献内存 

注意:
这里所说的开辟物理空间、建立映射等操作都是调用系统接口完成的,也就是说这些动作都由操作系统来完成。 

共享内存的建立与释放

共享内存的建立大致包括以下两个过程:

  1. 在物理内存当中申请共享内存空间。
  2. 将申请到的共享内存挂接到地址空间,即建立映射关系。

共享内存的释放大致包括以下两个过程:

  1. 将共享内存与地址空间去关联,即取消映射关系。
  2. 释放共享内存空间,即将物理内存归还给系统。
共享内存的创建 
shmget

创建共享内存我们需要用shmget函数,shmget函数的函数原型如下:

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

shmget函数的参数说明:

第一个参数key,表示待创建共享内存在系统当中的唯一标识。

key值一般不会随便设置(这个值独一无二的),一般用ftok()函数来获取key值

key_t ftok(const *pathname,int proj_id);
第一个参数是路径字符串
第二个参数是项目ID


第二个参数size,表示待创建共享内存的大小。
第三个参数shmflg,表示创建共享内存的方式。

第三个参数常用这个函数自带的宏选项,下面是两个常用选项IPC_CREAT和IPC_EXCL 


shmget函数的返回值说明:

shmget调用成功,返回一个有效的共享内存标识符(用户层标识符)。
shmget调用失败,返回-1。

 系统中有大量的共享内存同时存在,最终操作系统要管理所有的共享内存,这里就要用一个及结构体对象将共享内存描述起来管理struct shm(假设), 既共享内存=共享内存的内核数据结构+真正开辟的空间

key值设置测试

创建共享内存

server端,client同理

查看共享内存

在Linux当中,我们可以使用ipcs命令查看有关进程间通信设施的信息。

单独使用ipcs命令时,会默认列出消息队列、共享内存以及信号量相关的信息,若只想查看它们之间某一个的相关信息,可以选择携带以下选项:

  • -q:列出消息队列相关信息。
  • -m:列出共享内存相关信息。
  • -s:列出信号量相关信息。

 共享内存的释放

这里的共享内存 ,并不会随着进程的退出而释放,其生命周期是随操作系统的,一般要用指令或者系统接口释放,如上面的server端运行一次后共享内存依然存在,在下次运行就会出现报错,这就是因为没有释放共享内存

指令删除

我们可以使用ipcrm -m shmid命令释放指定id的共享内存资源。

接口删除 

shmctl

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmctl函数的参数说明:

第一个参数shmid,表示所控制共享内存的用户级标识符。
第二个参数cmd,表示具体的控制动作。
第三个参数buf,用于获取或设置所控制共享内存的数据结构。
shmctl函数的返回值说明:

shmctl调用成功,返回0。
shmctl调用失败,返回-1。

其中,作为shmctl函数的第二个参数传入的常用的选项有以下三个 

IPC_STAT  获取共享内存的当前关联值,此时参数buf作为输出型参数

注意:这里的获取共享内存当前的关联值需要权限,要将权限设置一下 

IPC_SET   在进程有足够权限的前提下,将共享内存的当前关联值设置为buf所指的数据结构中的值
IPC_RMID   删除共享内存段

共享内存的关联

虽然进程进程创建了共享内存,但是并不意味着进程能够使用这个共享内存,所以这里需要将进程和共享内存关联起来

shmat

void *shmat(int shmid, const void *shmaddr, int shmflg);

shmat函数的参数说明:

第一个参数shmid,表示待关联共享内存的用户级标识符。
第二个参数shmaddr,指定共享内存映射到进程地址空间的某一地址,通常设置为NULL,表示让内核自己决定一个合适的地址位置。
第三个参数shmflg,表示关联共享内存时设置的某些属性。
shmat函数的返回值说明:

shmat调用成功,返回共享内存映射到进程地址空间中的起始地址。
shmat调用失败,返回(void*)-1。

注意:创建内存时候要设置权限,否则创建出来的共享内存的默认权限为0,就没有权限关联 ,也就是nattch怎么运行都是0

同时运行server和client

共享内存的去关联 
shmdt
int shmdt(const void *shmaddr);

shmdt函数的参数说明:

  • 待去关联共享内存的起始地址,即调用shmat函数时得到的起始地址。

shmdt函数的返回值说明:

  • shmdt调用成功,返回0。
  • shmdt调用失败,返回-1。

client 

server

 用共享内存实现serve和client的简单通信

 comm.hpp

#ifndef __COMM_HPP__
#define __COMM_HPP__

#include <iostream>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <string>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>

using namespace std;

//  IPC_CREAT and IPC_EXCL
// 单独使用IPC_CREAT: 创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,获取已经存在的共享内存并返回
// IPC_EXCL不能单独使用,一般都要配合IPC_CREAT
// IPC_CREAT | IPC_EXCL: 创建一个共享内存,如果共享内存不存在,就创建之, 如果已经存在,则立马出错返回 -- 如果创建成功,对应的shm,一定是最新的!

#define PATHNAME "."
#define PROJID 0x6666

const int gsize = 4096; //暂时

key_t getKey()
{
    key_t k = ftok(PATHNAME, PROJID);
    if(k == -1)
    {
        cerr << "error: " << errno << " : " << strerror(errno) << endl;
        exit(1);
    }
    return k;
}

string toHex(int x)
{
    char buffer[64];
    snprintf(buffer, sizeof buffer, "0x%x", x);
    return buffer;
}

static int createShmHelper(key_t k, int size, int flag)
{
    int shmid = shmget(k, gsize, flag);
    if(shmid == -1)
    {
        cerr << "error: " << errno << " : " << strerror(errno) << endl;
        exit(2);
    }
    return shmid;
}

int createShm(key_t k, int size)
{
    umask(0);
    return createShmHelper(k, size, IPC_CREAT | IPC_EXCL | 0666);
}

int getShm(key_t k, int size)
{
    return createShmHelper(k, size, IPC_CREAT);
}

char* attachShm(int shmid)
{
    char *start = (char*)shmat(shmid, nullptr, 0);
    return start;
}

void detachShm(char *start)
{
    int n = shmdt(start);
    assert(n != -1);
    (void)n;
}

void delShm(int shmid)
{
    int n = shmctl(shmid, IPC_RMID, nullptr);
    assert(n != -1);
    (void)n;
}

#define SERVER 1
#define CLIENT 0

class Init
{
public:
    Init(int t):type(t)
    {
        key_t k = getKey();
        if(type == SERVER) shmid = createShm(k, gsize);
        else shmid = getShm(k, gsize);
        start = attachShm(shmid);
    }
    char *getStart(){ return start; }
    ~Init()
    {
        detachShm(start);
        if(type == SERVER) delShm(shmid);
    }
private:
    char *start;
    int type; //server or client
    int shmid;
};












#endif

client.cc

#include "comm.hpp"
#include <unistd.h>

int main()
{
    Init init(CLIENT);
    char *start = init.getStart();
    char c = 'A';

    while(c <= 'Z')
    {
        start[c - 'A'] = c;
        c++;
        start[c - 'A'] = '\0';
        sleep(1);
    }
    return 0;
}

server.cc

#include "comm.hpp"
#include <unistd.h>

int main()
{
    Init init(SERVER);
    char *start = init.getStart();

    int n = 0;
    while(n <= 30)
    {
        cout <<"client -> server# "<< start << endl;
        sleep(1);
        n++;
    }
    return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1365978.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分治法:分而治之

排序算法中的快速排序&#xff0c;归并排序都用了分治思想 题目描述&#xff1a; 题目地址&#xff1a;LeetCode 50 数组中的第K个最大元素 题目描述&#xff1a; 题目地址&#xff1a;LeetCode 215

基于ssm的高校智能培训管理系统分析与设计论文

摘 要 如今的年代&#xff0c;已经是步入信息社会了&#xff0c;不仅信息更新速度频繁&#xff0c;信息量也大&#xff0c;在信息时代必须有相应的处理信息的方法&#xff0c;如果还采用以前的结绳记事或者笔写纸记&#xff0c;不仅是信息录入效率上赶不上节奏&#xff0c;在信…

Superset二次开发之提高Charts下载图片分辨率

需求:图片变高清 现状:Charts下载图片功能,下载的图片分辨率太差,用户体验不友好 源码分析 路径1:superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx接口1:DOWNLOAD_AS_IMAGE路径2:superset-frontend/src/utils/downloadAsImage.ts接口2:d…

VmWare虚拟机的安装

VmWare官方最新版下载地址 vmware官方下载地址 安装流程 安装成功验证 安装完成之后&#xff0c;打开网络中心&#xff0c;一定要确认这里多出两个网络连接&#xff0c;才证明Vmware已经安装成功

静态网页设计——千姿百色旅游网(HTML+CSS+JavaScript)(dw、sublime Text、webstorm、HBuilder X)

前言 声明&#xff1a;该文章只是做技术分享&#xff0c;若侵权请联系我删除。&#xff01;&#xff01; 感谢大佬的视频&#xff1a; https://www.bilibili.com/video/BV1oe411m7kH/?vd_source5f425e0074a7f92921f53ab87712357b 源码&#xff1a;https://space.bilibili.co…

编码数据集生成框架 UnitGen 0.4.0:代码文档生成、测试代码生成

UnitGen 是我们从 UnitEval 拆分出来的代码数据集生成项目&#xff0c;旨在为基于开源模型供的私有化部署提供更好的编码数据集。 在结合开源模型 AutoDev 插件之后&#xff0c;你可以使用 UnitGen 结合企业内部现有的代码生成微调数据集&#xff0c;以让模型生成的代码更适合…

【大数据进阶第三阶段之Hive学习笔记】Hive安装

目录 1、环境准备 2、下载安装 3、配置环境变量 4、配置文件 4.1、配置hive-env.sh ​编辑4.2、配置hive-site.xml 5、上传配置jar 6、启动 1、环境准备 安装hadoop 以及 zookeeper、mysql 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行环境搭建-CSDN博客 《z…

AntDB内存管理之内存上下文之如何使用内存上下文

5.如何使用内存上下文 使用内存上下文之前&#xff0c;我们需要先对其进行创建。AntDB启动时已经创建并初始化好了部分内存上下文&#xff0c;例如&#xff1a;TopMemoryContext。这个TopMemoryContext是所有内存上下文的父节点或者祖先节点。一般我们创建的内存上下文都在Top…

【docker笔记】Docker容器数据卷

Docker容器数据卷 卷就是目录或者文件&#xff0c;存在于一个或多个容器中&#xff0c;由docker挂载到容器&#xff0c;但不属于联合文件系统&#xff0c;因此能够绕过Union File System提供一些用于持续存储或共享数据的特性 卷的设计目的就是数据的持久化&#xff0c;完全独…

西南地区直播产业市场规模分析,透视成都直播基地产业全景

直播电商已进入全民化发展&#xff0c;作为一种新型的电子商务形式&#xff0c;成都直播产业园利用互联网渠道进行营销&#xff0c;为用户提供更具高度互动性、专业性、丰富、直观、实时的全面购物体验。本年度&#xff0c;西南地区直播产业市场规模宏大&#xff0c;以成都为代…

mysql服务多实例运行

1、官网下载mysql安装包 https://downloads.mysql.com/archives/community/ 2、解压安装包 tar -zxvf mysql-8.1.0-linux-glibc2.28-aarch64.tar.xz -C /usr/localmv /usr/local/mysql-8.1.0-linux-glibc2.28-aarch64 /usr/local/mysql 3、创建mysql用户组 groupadd…

【面试】 前端竞争压力大?揭秘让你们学后端的真实动机!

前端开发属于程序员吗? 网友是这样回答的&#xff1a; 看完前端同学的评论&#xff0c;我悟了&#xff0c;你们让人都去学后端卷&#xff0c;然后减小前端竞争压力是吧&#xff1f; 哈哈哈&#xff0c;你们这帮老6…… 于是我去拿出了我收藏的 某前端招聘JD来盘一盘 那些…

APP加固技术及其应用

文章目录 引言 APP加固的概念 APP加固的方案 APP加固在实际开发中的应用 总结 引言 在移动应用开发过程中&#xff0c;APP加固技术起到了非常重要的作用。APP加固是将apk文件进行混淆加密&#xff0c;以防止别人反编译获取我们的源码和资源文件。目前市场上主流的APP加固…

【ros笔记】urdf文件

urdf文件属于xml文件&#xff0c;他的标签有&#xff1a; <robot name"robot_name"><!-- 看的见摸的着刚体用link --><link name"base_link"><!-- 可视化部分 --><visual><!-- 几何形状 --><geometry><!-- b…

VOSviewer分析知网文献以及图片导出

目录 1.结果展示&#xff1a;2.操作步骤&#xff1a;2.1创建图片&#xff1a;2.2调整图片&#xff1a;2.3保存图片&#xff1a; 小结&#xff1a; 1.结果展示&#xff1a; 2.操作步骤&#xff1a; 2.1创建图片&#xff1a; 在知网上搜索关键词&#xff0c;然后将所有文献以相…

SpringBoot怎么写一个自定义的starter,Gradle依赖引入starter的Jar包

1.新建一个Spring的项目myasset-spring-boot-starter 项目结构如下: 注意:不需要Application启动类 和 application.yml/application.properties文件 2. resources下添加spring.factories文件 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfigu…

Prometheus实战篇:Prometheus监控rabbitmq

Prometheus实战篇:Prometheus监控rabbitmq 准备环境 docker-compose安装rabbitmq 这里注意rabbitmq需要暴露2个端口 docker-compose.yaml version: 3 services:rabbitmq:image: rabbitmq:3.7.15-managementcontainer_name: rabbitmqrestart: alwaysvolumes:- /data/rabbitmq…

计算机网络(超级详细笔记)

使用教材计算机网络&#xff08;第8版&#xff09;&#xff08;谢希仁&#xff09; 第一章&#xff1a;概述 第二章&#xff1a;物理层 第三章&#xff1a;数据链路层 第四章&#xff1a;网络层 第五章&#xff1a;运输层 第六章&#xff1a;应用层 目…

【MIdjourney】图像角度关键词

本篇仅是我个人在使用过程中的一些经验之谈&#xff0c;不代表一定是对的&#xff0c;如有任何问题欢迎在评论区指正&#xff0c;如有补充也欢迎在评论区留言。 1.侧面视角(from side) 侧面视角观察或拍摄的主体通常以其侧面的特征为主要焦点&#xff0c;以便更好地展示其轮廓…

LVGL,tabview用实体按键切换tab的事件回调实现

文章目录 背景回调中可以实现的功能在选定的tab容器中创建其他控件 背景 接着上一篇&#xff08;LVGL&#xff0c;tabview用实体按键切换tab如何实现&#xff09;的问题&#xff0c;当tabview的tab可以绑定实体按键后&#xff0c;每次切换的触发事件回调中能做些什么呢&#x…