C++进程链接工具之通信器详解

C++进程链接工具之通信器详解

什么是C++进程链接工具之通信器

C++进程链接工具之通信器(又称共享内存通信器)是一种实现进程间通信的方式。它使用共享内存的方式,允许多个进程共享同一块内存区域,并利用操作系统提供的信号量等机制,实现对共享内存的并发访问。

通信器主要由以下三个部分组成:

  • 共享内存区域:即多个进程共享的内存区域,用于存储需要交换的数据。
  • 读写锁:用于多个进程对共享内存的读写操作的互斥控制。
  • 信号量:用于某些情况下的进程同步,如通知对方进程数据已经准备好等。

通信器的使用方法

通信器的使用主要包括以下几个步骤:

  1. 创建或链接共享内存区域:第一个进程需要创建共享内存区域,而后续的进程需要链接已经创建好的共享内存区域。共享内存区域的大小应该由所有进程协商确定,通常在创建时指定,并且应该足够容纳所有需要共享的数据。
  2. 获取读写锁:所有需要对共享内存进行读写操作的进程都需要获取读写锁。
  3. 进行数据交换:各进程直接进行数据交换,可以把共享内存视为一个全局变量。
  4. 释放读写锁:读写操作完成后,需要释放读写锁。
  5. 删除共享内存:通信完成后,第一个进程需要删除共享内存区域。

下面将通过两个示例说明如何使用通信器。

示例一:简单的进程间通信

假设有两个进程A和B,我们通过通信器实现它们之间的数据交换。

进程A的代码示例

#include <iostream>
#include <cstring>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>

using namespace std;

int main() {
    key_t key = ftok("/tmp/comm", 'a');
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    char* data = (char*)shmat(shmid, (void*)0, 0);
    sem_t* mutex = sem_open("/tmp/comm_mutex", O_CREAT, 0666, 1);
    sem_t* empty = sem_open("/tmp/comm_empty", O_CREAT, 0666, 1);
    sem_t* full = sem_open("/tmp/comm_full", O_CREAT, 0666, 0);

    while (true) {
        sem_wait(full);
        sem_wait(mutex);

        cout << "Process A read: " << data << endl;
        strcpy(data, "Hello B!");

        sem_post(mutex);
        sem_post(empty);
    }

    shmctl(shmid, IPC_RMID, 0);
    sem_unlink("/tmp/comm_mutex");
    sem_unlink("/tmp/comm_empty");
    sem_unlink("/tmp/comm_full");

    return 0;
}

进程B的代码示例

#include <iostream>
#include <cstring>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>

using namespace std;

int main() {
    key_t key = ftok("/tmp/comm", 'a');
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    char* data = (char*)shmat(shmid, (void*)0, 0);
    sem_t* mutex = sem_open("/tmp/comm_mutex", O_CREAT, 0666, 1);
    sem_t* empty = sem_open("/tmp/comm_empty", O_CREAT, 0666, 1);
    sem_t* full = sem_open("/tmp/comm_full", O_CREAT, 0666, 0);

    while (true) {
        sem_wait(empty);
        sem_wait(mutex);

        strcpy(data, "Hello A!");
        cout << "Process B read: " << data << endl;

        sem_post(mutex);
        sem_post(full);
    }

    shmctl(shmid, IPC_RMID, 0);
    sem_unlink("/tmp/comm_mutex");
    sem_unlink("/tmp/comm_empty");
    sem_unlink("/tmp/comm_full");

    return 0;
}

上述代码演示了进程A和进程B之间的简单通信过程。两个进程共享一个大小为1024字节的共享内存区域,其中单元格0用于进程A存储数据,单元格1用于进程B存储数据。读写锁和信号量使用了POSIX信号量库提供的相关函数。

如何运行示例代码

为了运行这个示例代码,需要在终端中执行以下命令:

$ g++ process_a.cpp -o process_a -lpthread
$ g++ process_b.cpp -o process_b -lpthread
$ ./process_a & ./process_b

代码运行后,将持续输出“Hello A!”和“Hello B!”。

示例二:使用通信器发送结构化数据

假设还是有两个进程A和B,我们需要把一个结构化的数据传送给B进程。

通信结构体定义

struct Data {
    int a;
    float b;
    char c[20];
};

进程A的代码示例

#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
#include "data.h"

using namespace std;

int main() {
    key_t key = ftok("/tmp/comm", 'a');
    int shmid = shmget(key, sizeof(Data), 0666 | IPC_CREAT);
    Data* data = (Data*)shmat(shmid, (void*)0, 0);
    sem_t* mutex = sem_open("/tmp/comm_mutex", O_CREAT, 0666, 1);
    sem_t* empty = sem_open("/tmp/comm_empty", O_CREAT, 0666, 1);
    sem_t* full = sem_open("/tmp/comm_full", O_CREAT, 0666, 0);

    while (true) {
        sem_wait(full);
        sem_wait(mutex);

        data->a++;
        data->b += 0.123;
        strncpy(data->c, "Hello B!", sizeof(data->c));

        sem_post(mutex);
        sem_post(empty);
    }

    shmctl(shmid, IPC_RMID, 0);
    sem_unlink("/tmp/comm_mutex");
    sem_unlink("/tmp/comm_empty");
    sem_unlink("/tmp/comm_full");

    return 0;
}

进程B的代码示例

#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
#include "data.h"

using namespace std;

int main() {
    key_t key = ftok("/tmp/comm", 'a');
    int shmid = shmget(key, sizeof(Data), 0666 | IPC_CREAT);
    Data* data = (Data*)shmat(shmid, (void*)0, 0);
    sem_t* mutex = sem_open("/tmp/comm_mutex", O_CREAT, 0666, 1);
    sem_t* empty = sem_open("/tmp/comm_empty", O_CREAT, 0666, 1);
    sem_t* full = sem_open("/tmp/comm_full", O_CREAT, 0666, 0);

    while (true) {
        sem_wait(empty);
        sem_wait(mutex);

        cout << "Process B read " << data->a << ", " << data->b << ", " << data->c << endl;

        sem_post(mutex);
        sem_post(full);
    }

    shmctl(shmid, IPC_RMID, 0);
    sem_unlink("/tmp/comm_mutex");
    sem_unlink("/tmp/comm_empty");
    sem_unlink("/tmp/comm_full");

    return 0;
}

示例二演示了进程A向进程B发送结构化数据的过程。这里使用了一个自定义的Data结构体来存储数据。进程A在共享内存中修改结构体的数据,而进程B从共享内存中读取数据,然后在控制台输出。注意到这里并没有使用strcpy函数,而是直接使用了strncpy函数,为了避免溢出。

如何运行示例代码

还是运行以下命令:

$ g++ process_a.cpp -o process_a -lpthread
$ g++ process_b.cpp -o process_b -lpthread
$ ./process_a & ./process_b

在运行时请注意,如果两个进程同时输出,会产生混乱的控制台输出。可以尝试将输出重定向到文件中以便观察。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++进程链接工具之通信器详解 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C中的char s[]和char *s有什么区别

    当我们声明一个字符数组(char array)或一个字符指针(char pointer)时,会用到char s[]和char *s两种写法。它们之间有以下区别: 内存分配方式不同 char s[]声明的是字符数组,也叫数组型字符串(array-style string)。它需要在定义的时候指定初始值,编译器会自动计算数组的大小,将内存分配到栈上,这个数组的大…

    C 2023年5月10日
    00
  • socket多人聊天程序C语言版(一)

    下面是“socket多人聊天程序C语言版(一)”的完整攻略。 一、前置知识 在学习本文前,需要掌握以下C语言知识:- socket编程基础- 线程基础- 指针基础 二、程序结构 本程序主要分为四个模块:客户端、服务端、公共头文件和Makefile。 1. 公共头文件 common.h:包含了各种结构体和宏定义,以及客户端和服务端公共使用的函数的声明。 2. …

    C 2023年5月23日
    00
  • 详解C#对XML、JSON等格式的解析

    详解C#对XML、JSON等格式的解析 XML解析 在C#中,可以通过System.Xml命名空间下的类库实现对XML格式的解析。主要的类包括: XmlDocument:表示一个XML文档,可以通过该类的实例对象进行读取、创建、编辑XML文档。 XmlNode:表示XML文档中的一个节点。 XmlElement:表示XML文档中的一个元素节点。 XmlAtt…

    C 2023年5月23日
    00
  • Java异常处理之try…catch…finally详解

    Java异常处理之try…catch…finally详解 什么是Java异常? Java中的异常指的是程序运行过程中出现的错误或意外情况。异常分为两类: 受检异常(checked exception):在方法的声明中必须声明抛出的异常,程序在调用此方法时,必须使用try-catch语句处理异常。 非受检异常(unchecked exception):…

    C 2023年5月23日
    00
  • Photoshop 打造溶液字母文字特效

    Photoshop 打造溶液字母文字特效 前言 此篇攻略将详细介绍如何利用 Photoshop 实现溶液字母文字特效。通过本篇文章的讲解,您将掌握以下技能: 制作基础文字效果 制作溶液材质效果 制作混合效果,完成溶液字母文字特效 准备工作 在开始制作溶液字母文字特效之前,请确保您已经安装好了最新版的 Photoshop,并准备好以下素材: 背景图片 字母素材…

    C 2023年5月22日
    00
  • C++初级线程管理

    C++初级线程管理是多线程编程中最基础的部分,它可以帮助开发者充分利用计算资源,提升程序的并发能力,从而提高程序的运行效率。下面是完整的C++初级线程管理攻略: 线程的概念和基本使用 线程的概念 线程是计算机程序执行流的最小单元,它是操作系统能够进行运算调度的基本单位。与进程不同,线程通常是在同一进程中执行的,因此共享同一份资源,包括内存空间、文件描述符和其…

    C 2023年5月22日
    00
  • 详解利用C语言如何实现简单的内存池

    利用C语言实现简单的内存池一般可以分为以下步骤: 步骤一:自定义内存池数据结构 首先,我们需要自定义一个内存池的数据结构,一般包含以下几个要素: 内存池的大小(即可分配的内存总大小) 内存块的大小(即每个可分配的内存块的大小) 空闲内存块的数量(即尚未被分配的内存块的数量) 内存块的首地址(即内存池的起始地址) 我们可以使用结构体来表示这些要素,例如: st…

    C 2023年5月23日
    00
  • C语言:十进制,BCD码互换详解

    C语言:十进制,BCD码互换详解 1. 什么是BCD码 BCD码是二进制编码十进制的简称。它的特点是将十进制的数字转换成二进制的形式,但是每个二进制数码的取值范围只能是0000到1001,而且这种编码方式不容易进行运算。这种编码方式广泛应用于数字电路设计中。 2. 十进制转BCD码 将十进制数字转换成BCD码的一个常见方法是利用位运算,可以将拆分出每一位数字…

    C 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部