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/zh-hk/n/332858.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
GLBNI的頭像GLBNI
上一篇 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

發表回復

登錄後才能評論