C++进程间通信的多种方式及实现

这篇具有很好参考价值的文章主要介绍了C++进程间通信的多种方式及实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、管道(Pipe):是一种半双工的通信方式,适用于具有亲缘关系的两个进程之间的通信。管道分为匿名管道和命名管道。

//下面是C++使用管道(Pipe)进行进程间通信的一个例子:
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

int main() {
    int fd[2];
    pid_t pid;
    char buffer[256];

    // 创建管道
    if (pipe(fd) < 0) {
        cerr << "Failed to create pipe." << endl;
        return 1;
    }
    
    // 创建子进程
    if ((pid = fork()) < 0) {
        cerr << "Failed to create child process." << endl;
        return 1;
    } else if (pid > 0) { // 父进程
        close(fd[0]); // 关闭读端
    
        string message = "Hello, child process.";
        write(fd[1], message.c_str(), message.length()); // 向管道写入数据
    
        wait(NULL); // 等待子进程结束
    } else { // 子进程
        close(fd[1]); // 关闭写端
    
        read(fd[0], buffer, sizeof(buffer)); // 从管道读取数据
        cout << "Message from parent process: " << buffer << endl;
    }
    
    return 0;

}

上述代码中,先调用pipe()函数创建了一个管道,并在fork()函数中创建了一个子进程。父进程向管道中写入一条消息,子进程从管道中读取该消息并输出到屏幕上。

需要注意的是,管道是半双工的通信方式,在本例中父进程和子进程各自拥有管道的一端,因此需要分别关闭对方不需要使用的端口,以避免出现死锁等问题。另外,当进程间通信结束后需要及时关闭管道,并在父进程中等待子进程结束。

2 、共享内存(Shared Memory):是一种高效的进程间通信方式,可以在多个进程之间共享同一块内存区域,需要使用信号量等同步机制保证数据的正确性。

下面是C++使用共享内存(Shared Memory)进行进程间通信的一个例子:

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>

using namespace std;

int main() {
    pid_t pid;
    int* shared_memory;
    const int SIZE = 4096; // 共享内存的大小

    // 创建共享内存
    int fd = shm_open("/my_shared_memory", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
    ftruncate(fd, SIZE);
    
    // 映射共享内存到进程地址空间
    shared_memory = (int*)mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    
    // 创建子进程
    if ((pid = fork()) < 0) {
        cerr << "Failed to create child process." << endl;
        return 1;
    } else if (pid > 0) { // 父进程
        sleep(1); // 等待子进程执行
    
        cout << "Message from child process: " << shared_memory[0] << endl;
        shared_memory[1] = 2021; // 向共享内存中写入一条消息
    
        wait(NULL); // 等待子进程结束
    
        // 删除共享内存
        munmap(shared_memory, SIZE);
        shm_unlink("/my_shared_memory");
    } else { // 子进程
        shared_memory[0] = 1024; // 向共享内存中写入一条消息
    }
    
    return 0;

}

上述代码中,先调用shm_open()函数创建了一个共享内存对象,并调用ftruncate()设置其大小。然后使用mmap()映射了该共享内存到进程地址空间中。父进程向共享内存写入一条消息,子进程读取该消息并向共享内存中写入另一条消息。

需要注意的是,共享内存可以被多个进程同时访问,因此需要使用信号量等同步机制来保证数据的正确性。另外,在进程间通信结束后需要及时解除共享内存的映射,并删除该共享内存对象。

3、消息队列(Message Queue):是一种可靠的进程间通信方式,允许一个进程向消息队列发送消息,另一个进程从该队列接收消息。

下面是C++使用消息队列(Message Queue)进行进程间通信的一个例子:

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>

using namespace std;

struct msgbuf {
    long type;
    char message[256];
};

int main() {
    pid_t pid;
    int msqid;
    key_t key = 1234;
    struct msgbuf message;

    // 创建消息队列
    if ((msqid = msgget(key, IPC_CREAT | 0666)) < 0) {
        cerr << "Failed to create message queue." << endl;
        return 1;
    }
    
    // 创建子进程
    if ((pid = fork()) < 0) {
        cerr << "Failed to create child process." << endl;
        return 1;
    } else if (pid > 0) { // 父进程
        sleep(1); // 等待子进程执行
    
        msgrcv(msqid, &message, sizeof(message), 2, 0); // 接收来自子进程的消息
        cout << "Message from child process: " << message.message << endl;
    
        message.type = 3;
        strcpy(message.message, "Hello, child process.");
        msgsnd(msqid, &message, sizeof(message), IPC_NOWAIT); // 向消息队列中发送消息
    
        wait(NULL); // 等待子进程结束
    
        // 删除消息队列
        msgctl(msqid, IPC_RMID, NULL);
    } else { // 子进程
        message.type = 2;
        strcpy(message.message, "Hello, parent process.");
        msgsnd(msqid, &message, sizeof(message), IPC_NOWAIT); // 向消息队列中发送消息
    
        msgrcv(msqid, &message, sizeof(message), 3, 0); // 接收来自父进程的消息
        cout << "Message from parent process: " << message.message << endl;
    }
    
    return 0;

}

上述代码中,先调用msgget()函数创建了一个消息队列,并使用key指定其唯一标识符。然后在fork()函数中创建了一个子进程。父进程向消息队列中发送一条消息,子进程读取该消息并向消息队列中发送另一条消息。

需要注意的是,消息队列是可靠的通信方式,在多个进程之间传递数据时不会出现丢失或错位等情况。另外,在进程间通信结束后需要及时删除消息队列。

4、信号量(Semaphore):是一种特殊的变量,主要用于多个进程对共享资源的访问控制问题,以保证程序正常运行。

下面是C++使用信号量(Semaphore)进行进程间通信的一个例子:

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sem.h>

using namespace std;

int main() {
    pid_t pid;
    int semid;
    key_t key = 1234;

    // 创建信号量
    if ((semid = semget(key, 1, IPC_CREAT | 0666)) < 0) {
        cerr << "Failed to create semaphore." << endl;
        return 1;
    }
    
    // 初始化信号量值为0
    union semun arg;
    arg.val = 0;
    semctl(semid, 0, SETVAL, arg);
    
    // 创建子进程
    if ((pid = fork()) < 0) {
        cerr << "Failed to create child process." << endl;
        return 1;
    } else if (pid > 0) { // 父进程
        cout << "Parent process is waiting for child process..." << endl;
    
        // 等待子进程释放信号量
        struct sembuf sb;
        sb.sem_num = 0;
        sb.sem_op = -1;
        sb.sem_flg = 0;
        semop(semid, &sb, 1);
    
        cout << "Child process released the semaphore." << endl;
    
        wait(NULL); // 等待子进程结束
    
        // 删除信号量
        semctl(semid, 0, IPC_RMID);
    } else { // 子进程
        cout << "Child process is releasing the semaphore..." << endl;
    
        // 释放信号量
        struct sembuf sb;
        sb.sem_num = 0;
        sb.sem_op = 1;
        sb.sem_flg = 0;
        semop(semid, &sb, 1);
    
        cout << "Semaphore released." << endl;
    }
    
    return 0;

}

上述代码中,先调用semget()函数创建了一个信号量,并使用key指定其唯一标识符。然后初始化信号量值为0。父进程在等待子进程释放信号量之前一直处于阻塞状态,子进程释放信号量后即可继续执行。需要注意的是,多个进程间对同一个信号量的操作会产生竞争关系,因此需要使用信号量来控制访问该共享资源的顺序。

另外,在进程间通信结束后需要及时删除信号量。

5、套接字(Socket):是一种网络编程技术,但也可用于实现进程间通信,支持不同主机上的进程进行通信。

下面是C++使用套接字(Socket)进行进程间通信的一个例子:

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>

using namespace std;

int main() {
    pid_t pid;
    int sockfd, newsockfd, portno;
    socklen_t clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;

    // 创建套接字
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        cerr << "Failed to create socket." << endl;
        return 1;
    }
    
    // 设置服务器地址结构体
    bzero((char*)&serv_addr, sizeof(serv_addr));
    portno = 8888;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    
    // 绑定套接字到端口号
    if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
        cerr << "Failed to bind socket." << endl;
        return 1;
    }
    
    // 监听套接字
    listen(sockfd, 5);
    
    // 创建子进程
    if ((pid = fork()) < 0) {
        cerr << "Failed to create child process." << endl;
        return 1;
    } else if (pid > 0) { // 父进程
        cout << "Parent process is waiting for child process..." << endl;
    
        clilen = sizeof(cli_addr);
        newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen); // 等待客户端连接
    
        bzero(buffer, 256);
        read(newsockfd, buffer, 255); // 从套接字中读取消息
        cout << "Message from child process: " << buffer << endl;
    
        string message = "Hello, child process.";
        write(newsockfd, message.c_str(), message.length()); // 向套接字中写入消息
    
        close(newsockfd); // 关闭新的套接字
        wait(NULL); // 等待子进程结束
    } else { // 子进程
        sleep(1); // 等待父进程执行
    
        // 连接服务器
        if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
            cerr << "Failed to connect to server." << endl;
            return 1;
        }
    
        string message = "Hello, parent process.";
        write(sockfd, message.c_str(), message.length()); // 向套接字中写入消息
    
        bzero(buffer, 256);
        read(sockfd, buffer, 255); // 从套接字中读取消息
        cout << "Message from parent process: " << buffer << endl;
    
        close(sockfd); // 关闭套接字
    }
    
    return 0;

}

上述代码中,先调用socket()函数创建了一个套接字。然后设置服务器地址结构体,并使用bind()函数将套接字绑定到指定的端口号上。调用listen()函数开始监听套接字,等待客户端连接。父进程在等待子进程连接之前一直处于阻塞状态,子进程连接上服务器后即可继续执行。需要注意的是,在多个进程间使用套接字进行通信时,需要指定不同的端口号来区分各个进程之间的连接。

另外,在进程间通信结束后需要及时关闭套接字,并在父进程中等待子进程结束。

6、文件映射(File Mapping):将磁盘上的文件映射到进程的地址空间中,多个进程可以同时对该文件进行读写操作,需要使用同步机制确保数据的完整性。

下面是C++使用共享内存(Shared Memory)进行进程间通信的一个例子:

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>

using namespace std;

int main() {
    pid_t pid;
    int shmid;
    key_t key = 1234;
    char* message;
    const char* data = "Hello, shared memory.";

    // 创建共享内存
    if ((shmid = shmget(key, 1024, IPC_CREAT | 0666)) < 0) {
        cerr << "Failed to create shared memory." << endl;
        return 1;
    }
    
    // 将共享内存映射到当前进程的地址空间中
    if ((message = (char*)shmat(shmid, NULL, 0)) == (char*)-1) {
        cerr << "Failed to attach shared memory to process." << endl;
        return 1;
    }
    
    // 创建子进程
    if ((pid = fork()) < 0) {
        cerr << "Failed to create child process." << endl;
        return 1;
    } else if (pid > 0) { // 父进程
        cout << "Parent process is waiting for child process..." << endl;
    
        sleep(1); // 等待子进程执行
    
        cout << "Message from child process: " << message << endl;
    
        wait(NULL); // 等待子进程结束
    
        // 删除共享内存
        shmctl(shmid, IPC_RMID, NULL);
    } else { // 子进程
        strcpy(message, data); // 向共享内存中写入消息
    
        // 解除共享内存映射
        shmdt((void*)message);
    
        exit(0); // 退出子进程
    }
    
    return 0;

}

上述代码中,先调用shmget()函数创建了一个共享内存,并使用key指定其唯一标识符。然后将共享内存映射到当前进程的地址空间中。父进程在等待子进程向共享内存中写入消息之前一直处于阻塞状态,子进程向共享内存中写入消息后即可解除共享内存映射并退出子进程。需要注意的是,不同进程之间对同一块共享内存的访问需要加锁,以避免数据竞争等问题。

另外,在进程间通信结束后需要及时删除共享内存。文章来源地址https://www.toymoban.com/news/detail-617855.html

到了这里,关于C++进程间通信的多种方式及实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux多进程(二)进程通信方式一 管道

    管道的是进程间通信(IPC - InterProcess Communication)的一种方式,管道的本质其实就是内核中的一块内存(或者叫内核缓冲区),这块缓冲区中的数据存储在一个环形队列中,因为管道在内核里边,因此我们不能直接对其进行任何操作。 因为管道数据是通过队列来维护的,我们先

    2024年04月29日
    浏览(25)
  • 【Linux C | 进程】Linux 进程间通信的10种方式(1)

    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭 🤣本文内容🤣:🍭介绍 🍭 😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭 本文未经允许,不得转发!!! 下表是进程间通

    2024年01月25日
    浏览(27)
  • 【Linux C | 进程】Linux 进程间通信的10种方式(2)

    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭 🤣本文内容🤣:🍭介绍 🍭 😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭 本文未经允许,不得转发!!! POSIX消息队列与

    2024年02月20日
    浏览(25)
  • C++ Windows进程间共享内存通信

    在项目工程中需要64位程序调用32位程序并加以通信。 实现了两个进程间的内存共享。 提示:以下是本篇文章正文内容,下面案例可供参考 1、进程间通信原理: 主要实现: • 系统使用内存映射文件,以便加载和执行. exe和DLL文件。这可以大大节省页文件空间和应用程序启动

    2024年02月03日
    浏览(33)
  • 基于I.MX6ULL的Linux C多线程物联网网关+STM32+Qt上位机+Linux C++多线程服务器(含web)的多种无线通信系统的智慧农场

    我国是农业大国,而非农业强国。近30年来农业高产量主要依靠农药化肥的大量投入,大部分化肥和水资源没有被有效利用而随地弃置,导致大量养分损失并造成环境污染。我国农业生产仍然以传统生产模式为主,传统耕种只能凭经验施肥灌溉,不仅浪费大量的人力物力,也

    2024年04月14日
    浏览(57)
  • Linux的多种init进程实现

    在内核启动时,内核会创建第一个进程(称为init进程,initialization)来启动系统中所有其他进程,它会将init进程载入虚拟内存。init的进程标识符PID通常为1。 在Linux中,有多种init进程实现,目前最流行的是以下两种。 Linux最初使用的是SysVinit(SysV)初始化方法,该方法基于

    2024年01月25日
    浏览(23)
  • 使用 C++ 方式实现 GBK 到 UTF-8 转码 (win / linux)

    C++ 存在多种方式实现 GBK 到 UTF-8 的转码 一般使用C++都会想到使用 Qt API QString 将 gbk 转为 utf-8 此种方式,可以转换 Windows 平台运行时的 gbk 编码的中文字符串为 utf-8 格式,linux 下需要使用 QTextCodec ,网上有很多,此处不做过多描述。 由于项目需要去掉 Qt 依赖,或者无法使用

    2024年02月09日
    浏览(34)
  • Linux/Ubuntu下多机间基于socket通信进行数据交互及C++代码实现

    项目需要两台主机(视觉端Nvidia AGX Xavier;控制端Intel NUC10i7)进行机器人位姿、关节指令等double数据传输,计划使用socket通信实现; 两台主机通过一条网线建立局域网,分别创建新的有线连接: 服务器端:ipv4:192.168.56.3;子网掩码:255.255.255.0;网关:192.168.56.1 客户端:i

    2024年02月02日
    浏览(36)
  • Linux实现查看文件内容的多种方式

    目录 1、more:分屏显示文件内容。 2、less:文本内容查看器 3、head -n:显示文件前n行到终端 4、tail -n:显示文件后n行到终端 5、实现实时查看文件内容(追踪文件)         除了使用vi/vim 编辑器查看文件内容和使用cat命令将文件所有内容展示到终端上以外,还有多种方式。

    2024年02月12日
    浏览(32)
  • linux c++ 根据进程名杀死一个进程

    一、知识点储备 环境:centos6 , x86,g++ 需求:输入参数:进程名和超时时间;功能:杀死超时的进程 杀死进程的方法 :前期考虑用boost::process库以达到跨平台的目的,但是学习之后发现该库是用来管理子进程的,不能用来杀死一个不相干的进程。在linux中杀死一个进程可以使

    2024年02月17日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包