插件窝 干货文章 C++如何在Linux中进行进程间通信

C++如何在Linux中进行进程间通信

include 进程 int std 943    来源:    2025-05-09

Linux下C++进程间通信(IPC)方法详解

在Linux系统中,C++程序可以通过多种方式实现进程间通信(IPC)。以下是主要的IPC方法及其实现方式:

1. 管道(Pipe)

管道是最简单的IPC方式,适用于有亲缘关系的进程。

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

int main() {
    int fd[2];
    pipe(fd); // 创建管道

    pid_t pid = fork();
    if (pid == 0) { // 子进程
        close(fd[1]); // 关闭写端
        char buf[100];
        read(fd[0], buf, sizeof(buf));
        std::cout << "Child received: " << buf << std::endl;
        close(fd[0]);
    } else { // 父进程
        close(fd[0]); // 关闭读端
        const char* msg = "Hello from parent";
        write(fd[1], msg, strlen(msg) + 1);
        close(fd[1]);
    }
    return 0;
}

2. 命名管道(FIFO)

命名管道可用于无亲缘关系的进程间通信。

// 创建FIFO (在shell中或使用mkfifo函数)
// mkfifo myfifo

// 写入进程
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int main() {
    int fd = open("myfifo", O_WRONLY);
    write(fd, "Hello FIFO", 10);
    close(fd);
    return 0;
}

// 读取进程
int main() {
    int fd = open("myfifo", O_RDONLY);
    char buf[100];
    read(fd, buf, sizeof(buf));
    std::cout << "Received: " << buf << std::endl;
    close(fd);
    return 0;
}

3. 共享内存

共享内存是最快的IPC方式,但需要同步机制。

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

int main() {
    key_t key = ftok("shmfile", 65);
    int shmid = shmget(key, 1024, 0666|IPC_CREAT);

    char *str = (char*)shmat(shmid, (void*)0, 0);

    std::cout << "Write data: ";
    std::cin >> str;
    std::cout << "Data written: " << str << std::endl;

    shmdt(str);
    // shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
    return 0;
}

4. 消息队列

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

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);

    msg_buffer message;
    message.msg_type = 1;

    std::cout << "Write data: ";
    std::cin >> message.msg_text;

    msgsnd(msgid, &message, sizeof(message), 0);
    std::cout << "Data sent: " << message.msg_text << std::endl;

    // 接收消息
    msgrcv(msgid, &message, sizeof(message), 1, 0);
    std::cout << "Data received: " << message.msg_text << std::endl;

    msgctl(msgid, IPC_RMID, NULL); // 删除消息队列
    return 0;
}

5. 信号量(Semaphore)

用于进程同步。

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

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

int main() {
    key_t key = ftok("semfile", 65);
    int semid = semget(key, 1, 0666 | IPC_CREAT);

    semun sem_union;
    sem_union.val = 1;
    semctl(semid, 0, SETVAL, sem_union);

    struct sembuf sb = {0, -1, 0}; // 锁定
    semop(semid, &sb, 1);

    std::cout << "Critical section" << std::endl;
    sleep(5);

    sb.sem_op = 1; // 解锁
    semop(semid, &sb, 1);

    semctl(semid, 0, IPC_RMID, sem_union); // 删除信号量
    return 0;
}

6. 套接字(Socket)

可用于不同主机或同一主机上的进程通信。

// 服务器端
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>

int main() {
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);

    sockaddr_in address;
    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);

    int new_socket = accept(server_fd, NULL, NULL);
    char buffer[1024] = {0};
    read(new_socket, buffer, 1024);
    std::cout << "Message: " << buffer << std::endl;

    close(new_socket);
    close(server_fd);
    return 0;
}

// 客户端
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);

    sockaddr_in serv_addr;
    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, "Hello from client", 17, 0);

    close(sock);
    return 0;
}

选择建议

  1. 简单通信:使用管道或命名管道
  2. 高性能需求:共享内存(配合信号量)
  3. 结构化消息:消息队列
  4. 网络通信:套接字
  5. 同步控制:信号量

每种方法都有其适用场景,选择时应考虑通信模式、性能需求、进程关系等因素。