首页 > 系统相关 >Linux进程通信 | 共享内存

Linux进程通信 | 共享内存

时间:2023-03-18 12:12:32浏览次数:53  
标签:shmaddr int 通信 exit Linux shmid 区段 共享内存

一、共享内存是什么

在Linux系统中,共享内存是一种IPC(进程间通信)方式,它可以让多个进程在物理内存中共享一段内存区域。

这种共享内存区域被映射到多个进程的虚拟地址空间中,使得多个进程可以直接访问同一段物理内存区域中的数据,从而实现进程间的高速数据交换和通信。

二、共享内存的原理

共享内存基于内核的支持。在共享内存中,内核维护了一块物理内存区域,并将其映射到多个进程的虚拟地址空间中。每个进程都可以使用指针来访问共享内存区域中的数据,就像它们访问自己的内存一样。

使用共享内存示例

三、共享内存的使用方法

相关函数介绍

shmget函数

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

用于创建或打开一个共享内存区段,具体参数如下:

参数 类型 说明
key key_t 共享内存区段的关键字,用于在多个进程间标识同一个共享内存区段。
size size_t 共享内存区段的大小,以字节为单位。
shmflg int 共享内存区段的访问权限和行为属性。

函数返回值为共享内存区段的标识符 shmid,用于标识已创建或已打开的共享内存区段。

shmat函数

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

用于将共享内存区段连接到当前进程的地址空间,具体参数如下:

参数 类型 说明
shmid int 共享内存区段的标识符,用于标识已创建或已打开的共享内存区段。
shmaddr const void* 共享内存区段连接到当前进程地址空间的起始地址,如果为 NULL,则由系统自动选择一个地址。
shmflg int 标志参数,指定共享内存区段的访问权限和行为属性。

函数返回值为共享内存区段连接到当前进程地址空间的起始地址,即指向共享内存区段的指针。

shmdt函数

int shmdt(const void *shmaddr);

用于断开进程与共享内存区段的连接,具体参数如下:

参数 类型 说明
shmaddr const void* 共享内存区段连接到当前进程地址空间的起始地址。

函数返回值为 0 表示成功,-1 表示失败。

shmctl函数

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

用于控制共享内存区段的行为,如删除、获取、设置共享内存区段的属性等,具体参数如下:

参数 类型 说明
shmid int 共享内存区段的标识符,用于标识已创建或已打开的共享内存区段。
cmd int 控制命令,指定对共享内存区段的操作类型。
buf struct shmid_ds* 指向共享内存区段属性结构体的指针,用于获取或设置共享内存区段的属性。

常用的cmd参数包括:

  • IPC_STAT:获取共享内存的状态信息,并将该信息存储在buf参数指向的结构体中。
  • IPC_SET:设置共享内存的状态信息,buf参数指向要设置的新值。
  • IPC_RMID:删除共享内存。

函数返回值为操作成功返回 0,失败返回 -1。

实例演示

以下是一个示例代码,其中一个程序用于写入共享内存,另一个程序用于读取共享内存。

写入程序

/* write.c */

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

#define SHM_SIZE 1024

int main()
{
    int shmid;
    char *shmaddr;
    char write_buf[SHM_SIZE];

    // 创建共享内存段
    shmid = shmget((key_t)1234, SHM_SIZE, 0666|IPC_CREAT);
    if (shmid == -1) {
        perror("shmget failed");
        exit(EXIT_FAILURE);
    }

    // 将共享内存段连接到当前进程
    shmaddr = (char*)shmat(shmid, 0, 0);
    if (shmaddr == (void*)-1) {
        perror("shmat failed");
        exit(EXIT_FAILURE);
    }

    // 从标准输入读取数据并将其写入共享内存
    while(1) {
        fgets(write_buf, SHM_SIZE, stdin);
        strncpy(shmaddr, write_buf, SHM_SIZE);
        if (strncmp(write_buf, "exit", 4) == 0) {
            break;
        }
    }

    // 断开共享内存连接
    if (shmdt(shmaddr) == -1) {
        perror("shmdt failed");
        exit(EXIT_FAILURE);
    }

    // 删除共享内存段
    if (shmctl(shmid, IPC_RMID, 0) == -1) {
        perror("shmctl failed");
        exit(EXIT_FAILURE);
    }
    
    printf("write exit\n");

    return 0;
}

读取程序

/* read.c */

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

#define SHM_SIZE 1024

int main()
{
    int shmid;
    char *shmaddr;
    char read_buf[SHM_SIZE];

    // 获取共享内存段
    shmid = shmget((key_t)1234, SHM_SIZE, 0666|IPC_CREAT);
    if (shmid == -1) {
        perror("shmget failed");
        exit(EXIT_FAILURE);
    }

    // 将共享内存段连接到当前进程
    shmaddr = (char*)shmat(shmid, 0, 0);
    if (shmaddr == (void*)-1) {
        perror("shmat failed");
        exit(EXIT_FAILURE);
    }

    // 从共享内存读取数据并输出到标准输出
    while(1) {
        strncpy(read_buf, shmaddr, SHM_SIZE);
        printf("Received message: %s\n", read_buf);
        if (strncmp(read_buf, "exit", 4) == 0) {
            printf("Received exit\n");
            break;
        }
        sleep(1);
    }

    // 断开共享内存连接
    if (shmdt(shmaddr) == -1) {
        perror("shmdt failed");
        exit(EXIT_FAILURE);
    }

    printf("read exit\n");
    
    return 0;
}
  • 编译这两个程序
gcc -o write write.c
gcc -o read read.c

在一个终端窗口中运行write, 输入消息,在另一个终端窗口中运行read,查看消息。

要退出程序,则在运行write的终端窗口中键入"exit",效果如下:

共享内存读写


四、 共享内存的注意事项

  • 使用共享内存需要注意以下几点:
  1. 同步问题:由于多个进程可以同时访问共享内存,因此必须要使用同步机制来保证数据的一致性和正确性。
  2. 内存泄漏:如果一个进程崩溃或者没有及时解除共享内存映射,就有可能导致内存泄漏的问题。
  3. 安全问题:共享内存是多个进程共享的,因此必须要注意数据的安全性和隐私性,避免敏感数据泄露。

五、 共享内存的使用技巧

  • 以下是一些共享内存的使用技巧:
  1. 分配内存时使用 shmget() 系统调用中的 IPC_PRIVATE 标记,可以确保共享内存的键值在系统中是唯一的,避免冲突和安全问题。
  2. 在读写共享内存之前,使用信号量或互斥锁等同步机制来保证数据的一致性和正确性。
  3. 在使用共享内存时,可以将共享内存区域按照固定大小进行分块,避免多个进程同时访问同一块内存区域的冲突。

小结

共享内存是一种高效、灵活、方便的进程间通信方式,可以用于在多个进程之间共享大量数据。

使用共享内存需要注意同步、安全和内存泄漏等问题,可以使用信号量、互斥锁等同步机制来保证数据的正确性。

以上,如果觉得对你有帮助,点个赞再走吧,这样@知微之见也有更新下去的动力!

也欢迎私信我,一起交流!

标签:shmaddr,int,通信,exit,Linux,shmid,区段,共享内存
From: https://www.cnblogs.com/Wayne123/p/17229686.html

相关文章

  • Rocky Linux 系列6 --- inotify-tools
    一、概念1.环境(1)RockyLinux9.1(2)inotify-tools3.22.1.02.概念inotify用于监控文件或目录的改变,当文件或目录发生改变时inotify将触发通知。3.承上启下(1......
  • 在Linux终端管理你的密码!
    大家好,我是良许。现在是互联网时代,我们每天都要跟各种APP、网站打交道,而这些东西基本上都需要注册才可以使用。但是账号一多,我们自己都经常记不清对应的密码了。有些小伙......
  • 你对Linux窗口管理程序Tmux了解吗
    tmux是linux中一种管理窗口的程序,不同于iTerm2,它提供了一个Session随时存储和恢复的功能(Session概念后面会介绍),detachSession(保持Session后台运行),然后重新attachS......
  • Linux恢复文件双手锏
    当你在系统中有意或无意地使用 shift+delete 组合键、删除选项,或是清空回收站的方式来删除一个文件时,该文件的内容并没有从硬盘(或是其它存储设备)上直接销毁。它仅仅是......
  • 使用旧电脑玩Linux
    今天给大家讲讲使用旧电脑玩 ,大家应该都知道旧电脑的硬件一般比较落后,特别是一些非常老的电脑,目前还在使用的是机械硬盘,如是要跑 windows 可想而知,但是 Linux 系统对......
  • 如何使用一台windows远程控制一台正在运行Linux系统的服务器(OpenSSH的使用)
    什么是OpenSSHOpenSSH是一款用于远程登录的连接工具,它使用SSH协议1。SSH协议可以用来进行远程控制或在计算机之间传送文件,比传统的方式更安全2。Windows系统默认安装......
  • Linux目录详解
    /bin:bin其实就是binary的缩写,/bin目录下存放的就是我们经常使用的Linux命令。/boot:该目录存放的是启动Linux时的一些核心文件,具体包含一些镜像文件和链接文件,因此这个目录......
  • MATLAB:linux启动
    https://ww2.mathworks.cn/help/matlab/matlab_env/start-matlab-on-linux-platforms.htmlhttps://ww2.mathworks.cn/help/matlab/ref/matlablinux.html根据官网提示,选......
  • 计算机网络与通信之数据链路控制
    今天的内容主要讲的是如何保证广域网中计算机的通信的可靠性:数据链路层概述点对点协议:PPP点对多点协议:CSMA/CD差错控制技术1.数据链路层概述链路层中的信道数据链路层使......
  • 计算机网络与通信之网络互联及通信
    这部分的内容主要围绕网络层来展开:​​网络层概述​​​​网际协议IPv4​​​​地址解析协议ARP​​​​网际控制报文协议ICMP​​​​互联网路由协议​​1.网络层概述网......