首页 > 系统相关 >进程间通信

进程间通信

时间:2024-08-25 13:15:27浏览次数:14  
标签:信号量 共享内存 int 通信 间通信 进程 include

进程间通信

进程间通信(Inter-Process Communication,IPC)是指在不同进程之间进行数据交换和信息传递的机制。常见的通信方式有:管道、消息队列、共享内存、信号量、socket。

管道(Pipe)

无名管道:

特点:只能在具有亲缘关系的进程之间使用(如父子进程)。它是半双工的,即数据只能在一个方向上流动,若要实现双向通信,需要建立两个管道。
示例用法:

     #include <iostream>
     #include <unistd.h>

     int main() {
         int pipefd[2];
         pipe(pipefd);

         if (fork() == 0) {
             // 子进程
             close(pipefd[1]);
             char buffer[100];
             read(pipefd[0], buffer, sizeof(buffer));
             std::cout << "Child received: " << buffer << std::endl;
             close(pipefd[0]);
         } else {
             // 父进程
             close(pipefd[0]);
             write(pipefd[1], "Hello from parent!", 19);
             close(pipefd[1]);
         }

         return 0;
     }

命名管道(FIFO):

特点:可以在不相关的进程之间进行通信。命名管道有一个文件名,可以通过这个文件名进行访问。它也是半双工的,但可以通过建立两个命名管道实现双向通信。
示例用法:

     #include <iostream>
     #include <fcntl.h>
     #include <sys/stat.h>
     #include <unistd.h>

     int main() {
         const char* fifoName = "myfifo";
         mkfifo(fifoName, 0666);

         if (fork() == 0) {
             // 子进程
             int fd = open(fifoName, O_RDONLY);
             char buffer[100];
             read(fd, buffer, sizeof(buffer));
             std::cout << "Child received: " << buffer << std::endl;
             close(fd);
         } else {
             // 父进程
             int fd = open(fifoName, O_WRONLY);
             write(fd, "Hello from parent!", 19);
             close(fd);
         }

         unlink(fifoName);
         return 0;
     }

消息队列(Message Queue)

特点:消息队列是一种独立于发送和接收进程的存储机制。进程可以向消息队列发送消息,也可以从消息队列接收消息。消息队列可以实现异步通信,发送进程不需要等待接收进程的响应。
示例用法:

   #include <iostream>
   #include <sys/ipc.h>
   #include <sys/msg.h>

   struct message {
       long mtype;
       char mtext[100];
   };

   int main() {
       key_t key = ftok("progfile", 65);
       int msgid = msgget(key, 0666 | IPC_CREAT);

       if (fork() == 0) {
           // 子进程
           struct message msg;
           msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0);
           std::cout << "Child received: " << msg.mtext << std::endl;
           msgctl(msgid, IPC_RMID, nullptr);
       } else {
           // 父进程
           struct message msg;
           msg.mtype = 1;
           strcpy(msg.mtext, "Hello from parent!");
           msgsnd(msgid, &msg, sizeof(msg.mtext), 0);
       }

       return 0;
   }

共享内存(Shared Memory)

特点:共享内存是最快的 IPC 方式之一,因为它允许不同的进程直接访问同一块物理内存区域。这避免了数据在进程之间的复制,提高了通信效率。但是,由于存在多个进程同时访问同一块内存的情况,需要考虑同步机制。而且共享内存在不同操作系统中的实现可能不同,所以使用共享内存的程序在不同平台的可移植性比较差。
示例用法:

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

   int main() {
       key_t key = ftok("shmfile", 65);
       int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
       char* shmaddr = (char*)shmat(shmid, nullptr, 0);

       if (fork() == 0) {
           // 子进程
           std::cout << "Child read from shared memory: " << shmaddr << std::endl;
           shmdt(shmaddr);
       } else {
           // 父进程
           strcpy(shmaddr, "Hello from parent!");
           wait(nullptr);
           shmdt(shmaddr);
           shmctl(shmid, IPC_RMID, nullptr);
       }

       return 0;
   }

信号量(Semaphore)

特点:信号量主要用于进程间的同步和互斥。它可以控制对共享资源的访问,确保多个进程不会同时访问同一资源而导致数据不一致。
示例用法:

   #include <iostream>
   #include <sys/ipc.h>
   #include <sys/sem.h>

   union semun {
       int val;
       struct semid_ds* buf;
       unsigned short* array;
   };

   void semaphoreWait(int semid) {
       struct sembuf sops = {0, -1, 0};
       semop(semid, &sops, 1);
   }

   void semaphoreSignal(int semid) {
       struct sembuf sops = {0, 1, 0};
       semop(semid, &sops, 1);
   }

   int main() {
       key_t key = ftok("semfile", 65);
       int semid = semget(key, 1, 0666 | IPC_CREAT);
       semun initVal = {1};
       semctl(semid, 0, SETVAL, initVal);

       if (fork() == 0) {
           // 子进程
           semaphoreWait(semid);
           std::cout << "Child accessed shared resource." << std::endl;
           semaphoreSignal(semid);
       } else {
           // 父进程
           semaphoreWait(semid);
           std::cout << "Parent accessed shared resource." << std::endl;
           semaphoreSignal(semid);
       }

       semctl(semid, 0, IPC_RMID);
       return 0;
   }

套接字(Socket)

特点:套接字不仅可以用于同一台机器上不同进程之间的通信,还可以用于不同机器上的进程之间的通信。它支持多种通信协议,如 TCP 和 UDP。
示例用法(基于 TCP 的进程间通信):
服务器端:

     #include <iostream>
     #include <cstring>
     #include <unistd.h>
     #include <arpa/inet.h>

     int main() {
         int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
         if (serverSocket == -1) {
             std::cerr << "Error creating server socket." << std::endl;
             return -1;
         }

         sockaddr_in serverAddress;
         serverAddress.sin_family = AF_INET;
         serverAddress.sin_addr.s_addr = INADDR_ANY;
         serverAddress.sin_port = htons(8888);

         if (bind(serverSocket, reinterpret_cast<struct sockaddr*>(&serverAddress), sizeof(serverAddress)) == -1) {
             std::cerr << "Error binding server socket." << std::endl;
             close(serverSocket);
             return -1;
         }

         if (listen(serverSocket, 5) == -1) {
             std::cerr << "Error listening for connections." << std::endl;
             close(serverSocket);
             return -1;
         }

         int clientSocket = accept(serverSocket, nullptr, nullptr);
         if (clientSocket == -1) {
             std::cerr << "Error accepting client connection." << std::endl;
             close(serverSocket);
             return -1;
         }

         char buffer[1024];
         ssize_t bytesRead = read(clientSocket, buffer, sizeof(buffer));
         if (bytesRead > 0) {
             std::cout << "Received from client: " << buffer << std::endl;
         }

         close(clientSocket);
         close(serverSocket);

         return 0;
     }

客户端:

     #include <iostream>
     #include <cstring>
     #include <unistd.h>
     #include <arpa/inet.h>

     int main() {
         int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
         if (clientSocket == -1) {
             std::cerr << "Error creating client socket." << std::endl;
             return -1;
         }

         sockaddr_in serverAddress;
         serverAddress.sin_family = AF_INET;
         serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
         serverAddress.sin_port = htons(8888);

         if (connect(clientSocket, reinterpret_cast<struct sockaddr*>(&serverAddress), sizeof(serverAddress)) == -1) {
             std::cerr << "Error connecting to server." << std::endl;
             close(clientSocket);
             return -1;
         }

         const char* message = "Hello from client!";
         send(clientSocket, message, strlen(message), 0);

         close(clientSocket);

         return 0;
     }

性能对比

管道(Pipe)

性能特点:

  • 无名管道通常比较快速,适用于父子进程之间的简单通信。由于数据在内存中传递,速度相对较快。
  • 命名管道在性能上稍逊于无名管道,因为它涉及到文件系统的操作。但是,命名管道可以在不相关的进程之间使用,提供了更大的灵活性。

适用场景:

  • 无名管道适用于简单的父子进程通信场景,例如在命令行中使用管道将一个命令的输出作为另一个命令的输入。
  • 命名管道适用于需要在不相关进程之间进行通信的场景,例如不同的应用程序之间的通信。

消息队列(Message Queue)

性能特点:

  • 消息队列提供了一种异步通信方式,发送进程不需要等待接收进程的响应。这可以提高系统的并发性。
  • 消息队列的性能取决于消息的大小和数量。较小的消息和较少的消息数量通常会导致更好的性能。
  • 消息队列的操作相对较慢,因为它涉及到内核的干预和系统调用。

适用场景:

  • 消息队列适用于需要异步通信的场景,例如在分布式系统中,不同的节点之间需要进行通信,但不需要立即响应。
  • 消息队列也适用于需要发送大量小消息的场景,例如在日志系统中,不同的进程可以将日志消息发送到消息队列中,然后由一个专门的进程进行处理。

共享内存(Shared Memory)

性能特点:

  • 共享内存是最快的进程间通信方式之一,因为它允许不同的进程直接访问同一块物理内存区域,避免了数据在进程之间的复制。
  • 共享内存的性能取决于内存的访问模式和并发访问的程度。如果多个进程同时访问共享内存,可能会出现竞争条件,需要使用同步机制来确保数据的一致性。
  • 共享内存的操作相对简单,不需要进行系统调用,因此可以提高系统的性能。

适用场景:

  • 共享内存适用于需要高效数据共享的场景,例如在高性能计算中,多个进程需要共享大量的数据。
  • 共享内存也适用于需要快速通信的场景,例如在实时系统中,不同的进程需要快速交换数据。

信号量(Semaphore)

性能特点:

  • 信号量主要用于进程间的同步和互斥,而不是用于数据传输。因此,它的性能主要取决于同步操作的频率和复杂性。
  • 信号量的操作相对较慢,因为它涉及到系统调用和内核的干预。
  • 信号量的性能还受到信号量的初始值和使用方式的影响。如果信号量的初始值设置不当,可能会导致死锁或性能下降。

适用场景:

  • 信号量适用于需要同步和互斥的场景,例如在多线程编程中,不同的线程需要访问共享资源,需要使用信号量来确保数据的一致性。
  • 信号量也适用于需要控制对共享资源的访问的场景,例如在数据库系统中,多个进程需要访问数据库,需要使用信号量来控制并发访问的程度。

套接字(Socket)

性能特点:

  • 套接字可以用于不同机器上的进程之间的通信,因此它的性能受到网络延迟和带宽的限制。
  • 套接字的操作相对较慢,因为它涉及到网络通信和系统调用。
  • 套接字的性能还受到通信协议的选择和使用方式的影响。例如,TCP 协议提供了可靠的通信,但相对较慢;UDP 协议提供了不可靠的通信,但相对较快。

适用场景:

  • 套接字适用于需要在不同机器上的进程之间进行通信的场景,例如在分布式系统中,不同的节点之间需要进行通信。
  • 套接字也适用于需要与外部系统进行通信的场景,例如在网络应用程序中,需要与服务器进行通信。

总体而言,共享内存通常是最快的进程间通信方式,但它需要谨慎使用同步机制来确保数据的一致性。管道和消息队列适用于简单的通信场景,而套接字适用于需要在不同机器上进行通信的场景。信号量主要用于同步和互斥,而不是用于数据传输。在选择进程间通信方式时,需要根据具体的应用场景和性能要求进行权衡。

标签:信号量,共享内存,int,通信,间通信,进程,include
From: https://www.cnblogs.com/zccblogs/p/18378860

相关文章

  • Linux | 深入探究Linux进程控制:从fork函数到进程等待再到进程替换
    目录1、进程的创建:fork函数          示例:2、父子进程的奇怪现象:为什么同一个地址有不同的值?——区分内存的虚拟地址和物理地址代码:利用fork函数的返回值进行父子进程分流,执行不同的代码块虚拟地址和物理地址:fork调用和地址空间的关系:3、进程的终止......
  • 【C语言】进程和线程详解
    目录C语言进程和线程详解1.进程和线程的对比2.进程的基本概念2.1进程的定义2.2进程的特点2.3进程的生命周期3.进程管理3.1进程创建3.2进程间通信(IPC)3.2.1管道(Pipe)4.线程的基本概念4.1线程的定义4.2线程的特点5.POSIX线程库5.1引用头文件5.2创建线程......
  • Linux下进程间的通信--信号
    信号的概念:在Linux操作系统中,信号是一种软件中断机制,用于通知进程某个事件已经发生。信号是Linux进程间通信(IPC)的一种简单且快速的方式,它可以用来处理各种异步事件,如用户输入、硬件事件或软件条件。信号的特点:进程可以选择阻塞某些信号,阻止这些信号的传递。每个信号都有一......
  • 进程间通信(管道,共享内存)包含原理剖析
    通信的本质因为进程具有独立性,我们要进行通信的成本一定不低,我们要先让不同的进程看到同一份资源,之后再进行通信。所以,通信的本质是:1.操作系统直接或间接给通信双方的进程提供内存空间2.要通信的进程,必须看到同一份资源!不同的通信类型的本质就是:上面所说的资源是OS中哪一个模......
  • Android开发 - Binder 类进程间通信(IPC)的机制解析
    什么是BinderBinder是一种用于进程间通信(IPC)的机制,允许不同的进程(或者不同的组件)相互交互,提供了跨进程通信(IPC)的基础。它允许一个进程中的对象(如服务)被另一个进程中的代码(如应用组件)调用。Binder是一种特殊的对象,它能够在不同进程之间传递数据和调用方法Binder的作用进......
  • Android开发 - IBinder 类实现跨进程通信(IPC)解析
    什么是IBinderIBinder类是一个重要的接口,常用于实现跨进程通信(IPC);IBinder允许不同的进程或组件之间相互传递数据和调用方法。主要用于实现进程间通信。它是Android中的一个底层机制,允许不同的应用或组件(即使它们在不同的进程中)通过IBinder对象进行数据交换和方法调用IB......
  • 联通云数据中心-全球的数字化进程贡献了力量
    在繁华的香港将军澳工业园区内,矗立着一座现代化、高科技的标志性建筑——中国联通(香港)将军澳智·云数据中心。这座由中国联通全资打造并精心运营的专用数据中心大楼,不仅是中国联通在境外布局的最大综合性电信服务枢纽,更是连接全球、服务世界的重要桥梁。 自2016年荣耀启航以来......
  • io进程----标准io
    大纲IO:input,output     标准IO  文件IO  文件属性获取  目录操作  库(动态库,静态库)进程:process(程序执行的过程)     进程基础,线程(同步,互斥,条件变量),进程间通信(无名管道pipe,有名管道fifo,信号signal,共享内存sharedmemory,信号灯集semphore......
  • windows核心编程 内核对象,创建进程(CreateProcess),管道(CreatePipe)
    windows核心编程内核对象,创建进程(CreateProcess),管道(CreatePipe)windows核心编程内核对象,创建进程(CreateProcess),管道(CreatePipe)文章目录windows核心编程内核对象,创建进程(CreateProcess),管道(CreatePipe)主进程创建子进程并运行Ping命令主进程创建子进程并运行Ping......
  • 重头开始嵌入式第二十六天(Linux系统编程 进程间通信 IPC)
    目录IPC进程间通信1.管道通信管道的特性使用流程无名管道1.创建并打开管道:2.无名管道的读写:3.关闭管道: close();4.使用例子:有名管道1、创建:mkfifo2、打开有名管道 open3、管道的读写: 文件IO4、关闭管道:5、卸载管道:remove();IPC进程间通信进程间通信(In......