当前位置: 首页 > article >正文

共享内存相关知识点

目录

一、把共享内存中的数据读出来后,共享内存中还有这个数据吗?

二、同一时间只允许一个进程访问共享内存吗?

三、pthread_mutex_destroy和 munmap函数的使用介绍

1. pthread_mutex_destroy

2. munmap


一、把共享内存中的数据读出来后,共享内存中还有这个数据吗?

        共享内存是什么?他是一种进程间的通信方法,允许多个进程访问同一块区域。当一个进程将数据写入共享内存后,其他进程可以读取这些数据。需要特别注意的是,共享内存中的内容不会因为读取而被删除或改变。

        原理解析:

        1、数据存储

                当一个进程将数据写入共享内存------>数据存储子啊共享内存区域中------->直至被显示修改或释放。

        2、读取数据:

                另一个进程读取共享内存数据------>只是读取存储在那里的值,并不会影响原有数据----->内存中仍保留元数据,其他进程仍可以访问。

        3、修改数据:

                如某个进程------>对共享内存中数据进行操作(例如,更新或覆盖数据)--->共享内存中实质数据被修改。

        实际上,只有在数据在被合法修改或共享内存被删除(例如,调用shmctl函数)时,数据才会消失。

例子:

假设有两个进程 Process A 和 Process B,并且它们都使用同一块共享内存来读取和写入数据。

  • Process A 写入数据到共享内存。
  • Process B 读取共享内存中的数据。

在这个过程中:

  • 数据读取Process B 读取数据后,共享内存中的数据依然存在。
  • 数据修改:如果 Process A 之后在共享内存中修改了数据,Process B 读取时将会看到更新后的数据。

注意事项

  • 同步:由于多个进程可以同时访问共享内存---------->因此在访问共享内存时需要注意同步问题,以避免数据竞争------->通常通过信号量、互斥锁等机制实现。
  • 内存管理:共享内存通常在不需要时------->通过特定的系统调用(如shmdt何shmctl)来卸载和释放,以防止内存泄漏。

        简言之,读共享内存中的数据并不会改变或删除者共享内存中的数据,直到明确的写操作或释放这个共享内存。

那我们来解决一下进程竞争

二、同一时间只允许一个进程访问共享内存吗?

        在使用共享内存进行进程间通信时,确实需要考虑到多个进程可能会同时访问同一块共享内存的问题。为了确保数据的一致性和完整性,通常需要使用同步机制来控制对共享内存的访问。以下是一些关键点:

1、同步机制

        由于共享内存允许多个进程同时访问,若没有适当的同步机制,可能会导致数据竞争(data race)和不一致的状态。为了解决这个问题,可以使用以下几种同步机制:

  • 互斥锁(Mutex):互斥锁可以确保同一时间只有一个进程对共享内存的访问。其他进程在尝试访问时被阻塞,直到持有锁的进程释放锁。

  • 信号量(Semaphore):信号量是一种更为灵活的同步机制,可以用于控制多个进程对共享内存资源的访问。可以使用二进制信号量(类似于互斥锁)来确保互斥访问,或使用计数信号量来允许一定数量的进程同时访问。

  • 读写锁(Read-Write Lock)允许多个进程同时读取共享内存,但在写入时会阻塞其他进程的读取或写入。这在读操作远多于写操作的场景下特别有效。

2、访问控制

在设计共享内存的使用时,通常会遵循以下原则:

  • 初始化同步机制:在进程访问共享内存之前,必须先初始化相应的同步机制。

  • 获取锁:在访问共享内存之前,进程应获取锁(或信号量),以防止其他进程同时访问。

  • 释放锁:访问完成后,进程应释放锁,以便允许其他进程访问共享内存。

3、示例代码

以下是一个简单的示例,展示如何使用互斥锁来控制对共享内存的访问:

#include <stdio.h>  
#include <stdlib.h>  
#include <pthread.h>  
#include <sys/mman.h>  
#include <unistd.h>  
#include <string.h>  

#define SHM_SIZE 1024  

// 共享内存和互斥锁  
char *shared_memory;  
pthread_mutex_t mutex;  

void *process_function(void *arg) {  
    // 获取锁  
    pthread_mutex_lock(&mutex);  
    
    // 读写共享内存 
    
    //(long)arg 将一个指针类型的变量值转换成整数类型,以进行数学运算或格式化输出。\
    使用long进行转换能够确保足够的位数以容纳地址(取决于编译器和平台定义)
    printf("Process %ld writing to shared memory...\n", (long)arg);  
    snprintf(shared_memory, SHM_SIZE, "Hello from process %ld", (long)arg);
      
    // 释放锁  
    pthread_mutex_unlock(&mutex);  
    
    return NULL;  
} 

int main()
{
    //创建共享内存
    shared_memory = mmap(NULL,SHM_SIZE,PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,-1,0);

    //初始化互斥锁
    pthread_mutex_init(&mutex,NULL);
    
    pthread_t threads[5];//创建一个线程数组
    
    //创建多个进程(线程)
    for(long i = 0; i < 5; i++)
    {
        pthread_create(&threads[i],NULL,thread_function,NULL);        
    }

    //等待所有线程完成
    for(int i = 0;i < 5;i++)
    {
        pthread_join(threads[i],NULL);
    }

    //打印共享内存内容
    printf("Final shared memory content: %s\n",shared_memory);

    //清理与释放
    pthread_mutex_destory(&mutex);
    munmap(shared_memory,SHM_SIZE);  


    return 0;  
}

 

三、pthread_mutex_destroy和 munmap函数的使用介绍

1. pthread_mutex_destroy
  • 功能pthread_mutex_destroy 函数用于销毁一个已经初始化的互斥锁(mutex)。这意味着该互斥锁不再可用,并且释放与该互斥锁相关联的资源。

  • 用法

    int pthread_mutex_destroy(pthread_mutex_t *mutex);
  • 参数

    • mutex:指向待销毁的互斥锁对象的指针。
  • 返回值

    • 如果成功,返回 0;如果发生错误,返回一个错误码。
  • 注意事项

    • 在调用 pthread_mutex_destroy 时,确保没有线程在使用该互斥锁(即,确保所有锁定已经解除并且所有线程都已结束),否则会导致未定义行为。
    • 在销毁之前,可以使用 pthread_mutex_lock 或 pthread_mutex_trylock 等函数检查互斥锁的状态。
2. munmap
  • 功能munmap 函数用于解除映射的内存区域,通常是在使用 mmap 进行内存映射后,用以释放该区域。它会将指定的内存区域从进程的地址空间中移除,释放地址空间。

  • 用法

    int munmap(void *addr, size_t length);
  • 参数

    • addr:指向要解除映射的内存区域的起始地址。
    • length:要解除映射的内存区域的大小(字节数)。
  • 返回值

    • 如果成功,返回 0;如果发生错误,返回 -1,并设置 errno 以指示错误原因。
  • 注意事项

    • 确保提供的 addr 和 length 与之前用于 mmap 的参数相匹配。
    • 解除映射之前,不应在该内存区域中访问数据(即,确保没有正在使用该内存区域的线程)。


http://www.kler.cn/a/373728.html

相关文章:

  • 【C++滑动窗口】2653. 滑动子数组的美丽值|1785
  • Android启动流程_SystemServer阶段
  • 数据库数据恢复—Oracle ASM磁盘组掉线 ,ASM实例无法挂载的数据恢复案例
  • 微信小程序中点击搜素按钮没有反应,可能是样式问题(按钮被其他元素覆盖或遮挡)
  • 基于深度学习的舆论分析与检测系统应用与研究
  • WPF+MVVM案例实战(十四)- 封装一个自定义消息弹窗控件(下)
  • 架构师备考-数据库基础
  • 安科瑞AM5SE-IS 防逆流保护装置 功能全面 逆功率保护
  • Linux安装部署数据库:MongoDB
  • Redis高级篇之bigKey理论介绍以及优化
  • STATCOM静止同步补偿器原理及MATLAB仿真模型
  • Windows1学习笔记
  • 易考八股文之SpringBoot的启动流程
  • 【UBuntu20 配置usb网卡】 记录Ubuntu20配置usb网卡(特别是建立热点)
  • 企业奇门与金蝶云星空的数据集成解决方案
  • 数据库编程 SQLITE3 Linux环境
  • 必应Bing国内搜索广告代理商,必应广告如何开户投放?
  • Flink + Kafka 实现通用流式数据处理详解
  • 钉钉报销数据与金蝶云星空系统的集成解决方案
  • 前端如何安全存储密钥,防止信息泄露
  • JS:列表操作
  • css-元素居中方式
  • 如何解决Java EasyExcel 导出报内存溢出
  • 使用 Python 实现分布式任务锁:详解与示例
  • RT8H8K001_RT6809CNN01/RT8889CNN03_SPI-4参考程序
  • 实现一个完整FPGA项目的流程