首页 > 系统相关 >详解IPC(进程间通信)

详解IPC(进程间通信)

时间:2024-09-17 17:51:37浏览次数:13  
标签:IPC int 间通信 buffer 详解 fd 进程 message include

进程间通信(IPC,Inter-Process Communication)是指在不同进程之间传递数据或信号的机制。由于进程之间的地址空间是独立的,IPC提供了一种在进程之间进行数据交换的方法。以下是几种常见的IPC机制:

1. 管道(Pipes)

匿名管道

匿名管道是单向的通信通道,通常用于具有亲缘关系的进程之间(如父子进程)。

#include <stdio.h>
#include <unistd.h>

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

    if (fork() == 0) {
        // 子进程
        close(fd[0]); // 关闭读端
        write(fd[1], "Hello, parent!", 15);
        close(fd[1]);
    } else {
        // 父进程
        char buffer[15];
        close(fd[1]); // 关闭写端
        read(fd[0], buffer, 15);
        printf("Received from child: %s\n", buffer);
        close(fd[0]);
    }
    
    return 0;
}
命名管道(FIFO)

命名管道可以在不相关的进程之间进行通信。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int main() {
    const char *fifo = "/tmp/my_fifo";
    mkfifo(fifo, 0666);
    if (fork() == 0) {
        // 子进程
        int fd = open(fifo, O_WRONLY);
        write(fd, "Hello, parent!", 15);
        close(fd);
    } else {
        // 父进程
        char buffer[15];
        int fd = open(fifo, O_RDONLY);
        read(fd, buffer, 15);
        printf("Received from child: %s\n", buffer);
        close(fd);
        unlink(fifo);
    }

    return 0;
}

2. 消息队列(Message Queues)

消息队列允许进程以消息的形式进行通信,消息可以按照优先级进行排序。

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct msg_buffer {
    long msg_type;
    char msg_text[100];
};

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

    if (fork() == 0) {
        // 子进程
        struct msg_buffer message;
        message.msg_type = 1;
        sprintf(message.msg_text, "Hello, parent!");
        msgsnd(msgid, &message, sizeof(message), 0);
    } else {
        // 父进程    
        struct msg_buffer message;
        msgrcv(msgid, &message, sizeof(message), 1, 0);
        printf("Received from child: %s\n", message.msg_text);
        msgctl(msgid, IPC_RMID, NULL);
    }

    return 0;
}

3. 共享内存(Shared Memory)

共享内存允许多个进程共享一块内存区域,是最快的IPC机制之一。

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

int main() {
    key_t key = ftok("shmfile", 65);
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    char *str = (char*) shmat(shmid, (void*)0, 0);
    
    if (fork() == 0) {
        // 子进程
        sprintf(str, "Hello, parent!");
        shmdt(str);
    } else {
        // 父进程
        sleep(1); // 确保子进程先写入
        printf("Received from child: %s\n", str);
        shmdt(str);
        shmctl(shmid, IPC_RMID, NULL);
    }

    return 0;
}

4. 信号(Signals)

信号是一种用于通知进程某个事件发生的机制。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void signal_handler(int signum) {
    printf("Received signal %d\n", signum);
}

int main() {
    signal(SIGUSR1, signal_handler);

    if (fork() == 0) {    
        // 子进程
        sleep(1); // 确保父进程先设置信号处理函数
        kill(getppid(), SIGUSR1);
        } else {
        // 父进程
        pause(); // 等待信号
    }

    return 0;
}

5. 套接字(Sockets)

套接字不仅可以用于同一台机器上的进程间通信,还可以用于不同机器之间的通信。

// 服务器端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};
    
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;    
    address.sin_port = htons(8080);
    
    bind(server_fd, (struct sockaddr *)&address, sizeof(address));

    listen(server_fd, 3);

    new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);

    read(new_socket, buffer, 1024);
    
    printf("Received from client: %s\n", buffer);

    close(new_socket);
    
    close(server_fd);
    
    return 0;
}
// 客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char *message = "Hello, server!";

    sock = socket(AF_INET, SOCK_STREAM, 0);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(8080);

    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);

    connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    send(sock, message, strlen(message), 0);

    close(sock);

    return 0;
}

总结

不同的IPC机制有不同的适用场景和优缺点:

  • 管道:适用于简单的父子进程通信。
  • 消息队列:适用于需要消息排序和优先级的场景。
  • 共享内存:适用于需要高效大数据量传输的场景。
  • 信号:适用于简单的事件通知。
  • 套接字:适用于网络通信和不同机器之间的通信。

选择合适的IPC机制可以提高程序的效率和可靠性。

标签:IPC,int,间通信,buffer,详解,fd,进程,message,include
From: https://blog.csdn.net/weixin_53442127/article/details/142316804

相关文章

  • STM32F407单片机编程入门(三)ADC详解及实战含源码
    文章目录一.概要二.STM32F407VET6单片机ADC外设特点三.STM32单片机ADC内部结构图1.ADC相关引脚说明2.ADC通道分类3.触发源4.转换周期5.电压转换计算6.更精确电压转换计算四.规则通道ADC采集信号流向1.单次转换模式2.连续转换模式五.CubeMX配置一个ADC采集例程六.CubeMX......
  • 全国职业技能大赛大数据应用开发赛题任务B详解
    1、写在前言关于本篇:博主在团队中主要负责数据抽取、数据清洗、数据代码部分的编写,也就是任务书中的任务B模块,因此本片博客内容主要也会集中在任务B题目上关于代码风格:任务B的内容基本都是和spark打交道,众所周知spark有两种编写风格sql风格、dsl风格。两种风格功能都是能实现......
  • python标准库模块 pickle 详解
    什么是pickle模块?pickle是Python的一个标准库,用于序列化和反序列化Python对象。所谓序列化,就是将一个Python对象转换成字节流,以便存储到磁盘或通过网络传输。反序列化则是将字节流恢复为原来的Python对象。为什么使用pickle?保存Python对象:可以将Python中的各......
  • Transformer详解
    1Transformer结构https://jalammar.github.io/illustrated-transformer/Transformer一个巨大的优点是:模型在处理序列输入时,可以对整个序列输入进行并行计算,不需要按照时间步循环递归处理输入序列。1.1Transformer宏观结构Transformer可以看作是seq2seq模型的一种,对比之前的RNN,......
  • C++内存管理详解:各类变量的存储区域
      在C++中,变量的存储位置取决于它们的类型和生命周期。那么不同的各个变量究竟存储在哪个区域呢?1.不同类型的变量我们首先从变量类型的不同来说明:1.全局变量和静态变量 -存储区:全局/静态区(静态区)-说明:全局变量(包括文件级和函数级的)和使用`static`关键字声明的变......
  • 二分详解——学习笔记
    首先,使用二分有几个前提:具有单调性要求“最小的最大”或“最大的最小”其次,还要分清楚二分查找与二分答案的区别:二分查找:在某区间使用二分的思想进行查找二分答案:在答案的区间中使用二分的思想并判断从而找到最优解同时还要处理好二分的边界。接下来来理解一下......
  • 跟着问题学10——RNN详解及代码实战
    1循环神经网络RecurrentNeuralNetwork什么是序列信息呢?通俗理解就是一段连续的信息,前后信息之间是有关系地,必须将不同时刻的信息放在一起理解。比如一句话,虽然可以拆分成多个词语,但是需要将这些词语连起来理解才能得到一句话的意思。RNN就是用来处理这些序列信息的任务......
  • 【MySQL】MySQL中JDBC编程——MySQL驱动包安装——(超详解)
    前言:......
  • 鸿蒙OS 线程间通信
    鸿蒙OS线程间通信概述在开发过程中,开发者经常需要在当前线程中处理下载任务等较为耗时的操作,但是又不希望当前的线程受到阻塞。此时,就可以使用EventHandler机制。EventHandler是HarmonyOS用于处理线程间通信的一种机制,可以通过[EventRunner]创建新线程,将耗时的操作......
  • 指针详解(中秋版)
       久违的键盘声,熟悉的思绪,仿佛时间在这一刻凝固。距离我上一次敲击键盘写下文字,已不知过了多少个日夜。但文字的魅力就在于,它总能跨越时间的长河,将我们的心灵再次相连。今天,我带着满心的感慨与新的故事,重新坐到了屏幕前。让我们一起,再次启程,探索文字的奥秘。(一)理解......