C++进程间通信

一、管道

1、管道概述

管道是一种基于内存的进程间通信方法,分为无名管道和有名管道。无名管道只能用于父子进程间通信,有名管道可用于任意进程间通信。

无名管道(匿名管道)实际上是一块内存缓冲区,严格遵循先进先出的原则。其中一个进程把数据写入缓冲区,另一个进程从缓冲区取出数据,读取和写入时分别用到管道的读端和写端。父进程调用fork之后,子进程的管道描述符和父进程完全独立。如果父进程调用了close,子进程并不会受到影响。另外,管道只能用于单向通信。

有名管道(FIFO)也是一种基于内存的进程通信方式,相对于无名管道可以用于任意进程间通信。有名管道存在于文件系统中,因此允许无亲缘关系进程间通信。

2、使用管道进行进程间通信

#include 
#include 
#include 

#define MSGSIZE 16

int main()
{
    char* msg = "Hello, world!";
    char inbuf[MSGSIZE];
    int p[2], pid;

    if (pipe(p)  0) {
        close(p[0]);
        write(p[1], msg, MSGSIZE);
        close(p[1]);
    } else if (pid == 0) {
        close(p[1]);
        read(p[0], inbuf, MSGSIZE);
        printf("%s\n", inbuf);
        close(p[0]);
    } else {
        fprintf(stderr, "fork failed\n");
        exit(2);
    }

    return 0;
}

二、消息队列

1、消息队列概述

消息队列是一种进程间通信的方式,进程可以通过消息队列来传递数据。消息队列在内核中维护,提供收发的缓存区,它是一种比较可靠的IPC机制。其中,每个消息都有一个类型属性,接收进程可以选择接收指定类型的消息。

2、使用消息队列进行进程间通信

#include 
#include 
#include 
#include 
#include 

#define MSGSZ 128

struct msgbuf {
    long mtype;
    char mtext[MSGSZ];
};

int main()
{
    int msqid;
    key_t key;
    struct msgbuf sndbuf, rcvbuf;

    if ((key = ftok(".", 'A')) == -1) {
        perror("ftok");
        exit(1);
    }

    if ((msqid = msgget(key, IPC_CREAT | 0666)) == -1) {
        perror("msgget");
        exit(1);
    }

    sndbuf.mtype = 1;
    sprintf(sndbuf.mtext, "hello, world!");
    if (msgsnd(msqid, &sndbuf, MSGSZ, IPC_NOWAIT) == -1) {
        perror("msgsnd");
        exit(1);
    }

    if (msgrcv(msqid, &rcvbuf, MSGSZ, 1, 0) == -1) {
        perror("msgrcv");
        exit(1);
    }
    printf("receive: %s\n", rcvbuf.mtext);

    if (msgctl(msqid, IPC_RMID, 0) == -1) {
        perror("msgctl");
        exit(1);
    }

    return 0;
}

三、信号量

1、信号量概述

信号量是一种进程间通信的方式,它用来保持多个进程之间同步或互斥。其中,信号量的值用来表示可用资源的个数,进程可以通过执行P操作(申请资源)和V操作(释放资源)来更改信号量的值。当信号量的值为0时,执行P操作的进程会进入阻塞状态。

2、使用信号量进行进程间通信

#include 
#include 
#include 
#include 
#include 

#define SEM_NUM 1

int main()
{
    key_t key;
    int semid, shmid;
    char *shmaddr;
    struct sembuf sembuf;

    if ((key = ftok(".", 'A')) == -1) {
        perror("ftok");
        exit(1);
    }

    if ((semid = semget(key, SEM_NUM, IPC_CREAT | 0666)) == -1) {
        perror("semget");
        exit(1);
    }

    if ((shmid = shmget(key, 1024, IPC_CREAT | 0666)) == -1) {
        perror("shmget");
        exit(1);
    }

    if ((shmaddr = shmat(shmid, NULL, 0)) == (void *)-1) {
        perror("shmat");
        exit(1);
    }

    sembuf.sem_num = 0;
    sembuf.sem_op = 1;
    sembuf.sem_flg = SEM_UNDO;
    semctl(semid, 0, SETVAL, 1);

    if (fork() == 0) {
        sembuf.sem_op = -1;
        semop(semid, &sembuf, 1);
        printf("child process write\n");
        sprintf(shmaddr, "hello, world!");
        sembuf.sem_op = 1;
        semop(semid, &sembuf, 1);
        exit(0);
    } else {
        sembuf.sem_op = -1;
        semop(semid, &sembuf, 1);
        printf("parent process read: %s\n", shmaddr);
        sembuf.sem_op = 1;
        semop(semid, &sembuf, 1);
    }

    return 0;
}

四、共享内存

1、共享内存概述

共享内存是一种高效的进程间通信方式,它通过将内存缓冲区映射到多个进程的虚拟地址空间,让多个进程之间共享数据。共享内存通常需要配合其他进程同步机制,如信号量一起使用。但存在一个问题,即多个进程共享内存容易引发数据一致性问题。

2、使用共享内存进行进程间通信

#include 
#include 
#include 
#include 

int main()
{
    int shmid, pid;
    char *shmaddr;

    if ((shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666)) == -1) {
        perror("shmid");
        exit(1);
    }

    if ((shmaddr = shmat(shmid, NULL, 0)) == (void *)-1) {
        perror("shmat");
        exit(1);
    }

    if ((pid = fork()) == 0) {
        printf("child process write\n");
        strcpy(shmaddr, "hello, world!");
        exit(0);
    } else if (pid > 0) {
        wait(NULL);
        printf("parent process read: %s\n", shmaddr);
    } else {
        perror("fork");
        exit(1);
    }

    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
        perror("shmctl");
        exit(1);
    }

    return 0;
}

原创文章,作者:GLBNI,如若转载,请注明出处:https://www.506064.com/n/332858.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
GLBNIGLBNI
上一篇 2025-01-27 13:34
下一篇 2025-01-27 13:34

相关推荐

  • 如何通过jstack工具列出假死的java进程

    假死的java进程是指在运行过程中出现了某些问题导致进程停止响应,此时无法通过正常的方式关闭或者重启该进程。在这种情况下,我们可以借助jstack工具来获取该进程的进程号和线程号,…

    编程 2025-04-29
  • 跨域通信浮标——实现客户端之间的跨域通信

    本文将介绍跨域通信浮标的使用方法,该浮标可以实现客户端之间的跨域通信,解决了浏览器同源策略的限制,让开发者能够更加方便地进行跨域通信。 一、浮标的原理 跨域通信浮标的原理是基于浮动…

    编程 2025-04-27
  • Java中的僵尸进程简介与解决方法

    本文将对Java中的僵尸进程进行详细阐述,并给出几种解决方法。 一、僵尸进程的概念 在操作系统中,进程是指正在执行的程序。当一个进程创建了一个子进程,而该子进程完成了任务却没有被父…

    编程 2025-04-27
  • 通信专业Python和Java的开发技巧

    本文旨在介绍通信专业Python和Java的开发技巧,为读者提供实用且可操作的思路和方法。 一、Python在通信领域中的应用 Python是一种优秀的程序设计语言,因其易学易用、…

    编程 2025-04-27
  • 多线程和多进程的应用

    多线程和多进程是现代编程中常用的技术,可以提高程序的效率和性能。本文将从不同的角度对多线程和多进程进行详细的介绍和应用。 一、多线程 vs 多进程 多线程和多进程都是为了实现程序并…

    编程 2025-04-27
  • Python多进程读取数据

    本文将从多个方面详细阐述在Python中如何通过多进程读取数据,并给出完整的代码示例。 一、多进程概述 在计算机科学中,进程是正在执行的程序实例。多进程是指计算机系统同时执行多个进…

    编程 2025-04-27
  • 进程a与进程b共享变量s1

    本文将从多个方面对进程a与进程b共享变量s1做详细的阐述,并给出代码示例。 一、定义全局变量s1 进程a与进程b共享变量s1,意味着s1是一个全局变量。在C语言中,可以使用关键字e…

    编程 2025-04-27
  • python多进程并行循环

    在大数据时代,我们通常需要处理大量的数据。处理大数据往往需要较长的时间,影响效率。Python提供了多线程、多进程等并行处理方式来提高数据处理效率。本文将主要讲解python多进程…

    编程 2025-04-27
  • Python进程池共享内存用法介绍

    本文将从多个方面详细阐述Python进程池共享内存的相关知识,包括如何使用进程池、进程池的实现原理、进程池中的共享内存管理等。本文内容将涵盖: 一、进程池的使用 进程池是一种有效的…

    编程 2025-04-27
  • ROS通信

    一、概述 ROS是机器人操作系统,是一个开源的、灵活的、分布式的软件平台,可以帮助我们快速开发机器人应用程序。ROS中的通信是机器人应用程序开发中最重要的部分之一,它是实现多模块协…

    编程 2025-04-25

发表回复

登录后才能评论