Linux进程间通信之《共享内存》入门

简介: 共享内存是Linux系统进程间通信常用的方式,通常用于数据量较大的情况,如果只是用于不同的进程间消息通知,那不如用消息队列或者socket。之前做的项目中,使用共享内存的其实只有一种情况:视频数据的共享。设备类似于DVR,视频采集编码在一个独立的程序中,另一个程序负责协议通信。共享内存要想好用,共享的那段内存,需要用数据结构和队列组织起来,加上读写索引和数据有效标志(已读和未读、可读)。下面的这个示例代码是我初学时的,适合入门和了解使用流程。

 目录

简述

代码

写端代码

读取端代码

编译

运行




代码

写端代码

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#define N 1024
typedef struct
{
    pid_t pid;
    char text[N];
}SHMBUF;
void handler(int signo) {printf("signo=%d\n", signo);}
int main()
{
  int shmid;
    SHMBUF *shmadd;
    key_t key;
    pid_t peerpid;
    if ((key = ftok(".", 'a')) == -1)
    {
        perror("ftok");
        exit(-1);
    }
    signal(SIGUSR1, handler);
  if ((shmid = shmget(key, sizeof(SHMBUF), 0666 | IPC_CREAT | IPC_EXCL)) == -1)
  {
        if (errno == EEXIST)
        {
            shmid = shmget(key, sizeof(SHMBUF), 0666);
          if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
          {
            perror("shmat");
            exit(-1);
          }
            peerpid = shmadd->pid;
            shmadd->pid = getpid();
            kill(peerpid, SIGUSR1);
        }
        else
        {
          perror("shmget");
        exit(-1);
        }
  }
    else    //first process
    {
      if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
      {
        perror("shmat");
        exit(-1);
      }
        shmadd->pid = getpid();
        //sprintf(shmadd, "%d", getpid());
        pause();
        peerpid = shmadd->pid;
    }
    printf(">");
    while (1)
    {
        fgets(shmadd->text, N, stdin);
        shmadd->text[strlen(shmadd->text)-1] = '\0';
        kill(peerpid, SIGUSR1);
        if (strncmp(shmadd->text, "quit", 4) == 0)
        {
            sleep(1);
          if (shmdt(shmadd) == -1)
          {
            perror("shmdt");
          }
          if (shmctl(shmid, IPC_RMID, NULL) == -1)
          {
            perror("RM");
            exit(-1);
          }
            exit(0);
        }
        pause();
        printf(">");
    }
  return 0;
}

image.gif

读取端代码

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#define N 1024
typedef struct
{
    pid_t pid;
    char text[N];
}SHMBUF;
void handler(int signo) {printf("signo=%d\n", signo);}
int main()
{
  int shmid;
    SHMBUF *shmadd;
    key_t key;
    pid_t peerpid;
    if ((key = ftok(".", 'a')) == -1)
    {
        perror("ftok");
        exit(-1);
    }
    signal(SIGUSR1, handler);
  if ((shmid = shmget(key, sizeof(SHMBUF), 0666 | IPC_CREAT | IPC_EXCL)) == -1)
  {
        if (errno == EEXIST)
        {
            shmid = shmget(key, sizeof(SHMBUF), 0666);
          if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
          {
            perror("shmat");
            exit(-1);
          }
            peerpid = shmadd->pid;
            shmadd->pid = getpid();
            kill(peerpid, SIGUSR1);
        }
        else
        {
          perror("shmget");
        exit(-1);
        }
  }
    else    //first process
    {
      if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
      {
        perror("shmat");
        exit(-1);
      }
        shmadd->pid = getpid();
        pause();
        peerpid = shmadd->pid;
    }
    while (1)
    {
        pause();
        printf("read %s\n", shmadd->text);
        if (strncmp(shmadd->text, "quit", 4) == 0)
        {
          if (shmdt(shmadd) == -1)
          {
            perror("shmdt");
          }
            exit(0);
        }
       // sleep(1);
       usleep(100000);
       kill(peerpid, SIGUSR1);
    }
    exit(0);
}

image.gif

编译

gcc reader.c -o reader
gcc writer.c -o writer

image.gif

运行

image.gif编辑


目录
相关文章
|
2月前
|
Java 数据库连接 测试技术
SpringBoot入门 - 添加内存数据库H2
SpringBoot入门 - 添加内存数据库H2
80 3
SpringBoot入门 - 添加内存数据库H2
|
2月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
555 6
|
2月前
|
缓存 Java Linux
如何解决 Linux 系统中内存使用量耗尽的问题?
如何解决 Linux 系统中内存使用量耗尽的问题?
158 48
|
1月前
|
C语言 开发者 内存技术
探索操作系统核心:从进程管理到内存分配
本文将深入探讨操作系统的两大核心功能——进程管理和内存分配。通过直观的代码示例,我们将了解如何在操作系统中实现这些基本功能,以及它们如何影响系统性能和稳定性。文章旨在为读者提供一个清晰的操作系统内部工作机制视角,同时强调理解和掌握这些概念对于任何软件开发人员的重要性。
|
29天前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
1月前
|
Linux 调度 C语言
深入理解操作系统:从进程管理到内存优化
本文旨在为读者提供一次深入浅出的操作系统之旅,从进程管理的基本概念出发,逐步探索到内存管理的高级技巧。我们将通过实际代码示例,揭示操作系统如何高效地调度和优化资源,确保系统稳定运行。无论你是初学者还是有一定基础的开发者,这篇文章都将为你打开一扇了解操作系统深层工作原理的大门。
|
2月前
|
缓存 Ubuntu Linux
Linux环境下测试服务器的DDR5内存性能
通过使用 `memtester`和 `sysbench`等工具,可以有效地测试Linux环境下服务器的DDR5内存性能。这些工具不仅可以评估内存的读写速度,还可以检测内存中的潜在问题,帮助确保系统的稳定性和性能。通过合理配置和使用这些工具,系统管理员可以深入了解服务器内存的性能状况,为系统优化提供数据支持。
46 4
|
2月前
|
算法 调度 开发者
深入理解操作系统:从进程管理到内存分配
本文旨在为读者提供一个深入浅出的操作系统知识之旅,从进程管理的基础概念出发,探索内存分配的策略与技巧。我们将通过实际代码示例,揭示操作系统背后的逻辑与奥秘,帮助读者构建起对操作系统工作原理的直观理解。文章不仅涵盖理论知识,还提供实践操作的指导,使读者能够将抽象的概念转化为具体的技能。无论你是初学者还是有一定基础的开发者,都能在这篇文章中找到有价值的信息和启发。
|
2月前
|
算法 调度 C++
深入理解操作系统:从进程管理到内存分配
【10月更文挑战第42天】本文将带你进入操作系统的神秘世界,探索其核心概念和关键技术。我们将从进程管理开始,了解操作系统如何协调和管理多个程序的运行;然后,我们将深入研究内存分配,看看操作系统如何有效地分配和管理计算机的内存资源。通过这篇文章,你将获得对操作系统工作原理的深入理解,并学会如何编写高效的代码来利用这些原理。
|
2月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?

热门文章

最新文章