自学内容网 自学内容网

Linux 进程间通信

Linux进程间通信

进程间通信(IPC,Inter-Process Communication)在 Linux 下常用的方法包括:

1)管道(Pipe)
2)有名管道(FIFO)
3)消息队列(Message Queue)
4)共享内存(Shared Memory)
5)信号量(Semaphore)
6)套接字(Socket)

1. 管道(Pipe)

管道是一种最基本的 IPC 方法,适用于有亲缘关系的进程之间通信。

管道(Pipe)参考代码

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

int main() {
    int ret = 0;
    int pipefd[2];
    pid_t pid;
    char buffer[1024];

    //创建管道
    ret = pipe(pipefd);
    std::cout <<"ret = " << ret << std::endl;
    if (ret == -1) { //当ret为-1时,说明pipe函数发生错误执行失败
        perror("pipe");
        return 1;
    }

    pid = fork();  //创建子进程

    std::cout << "pid= "  << pid << std::endl;
    if (pid < 0) {
        perror("fork");
        return 1;
    }

    if (pid == 0) {  // 子进程
        close(pipefd[0]);  // 关闭读端
        const char* message = "Hello from child process!";
        write(pipefd[1], message, strlen(message) + 1);
        close(pipefd[1]);  // 关闭写端
    } else {  // 父进程
        close(pipefd[1]);  // 关闭写端
        read(pipefd[0], buffer, sizeof(buffer));
        std::cout << "Parent received: " << buffer << std::endl;
        close(pipefd[0]);  // 关闭读端
    }

    return 0;
}

管道(Pipe)输出结果

ret = 0
pid= 26087
pid= 0
Parent received: Hello from child process!

2. 有名管道(FIFO)

适用于不相关的进程。

有名管道(FIFO)参考代码

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

#define FIFO_PATH "/tmp/myfifo"

int main() {
    pid_t pid;
    char buffer[1024];

    // 创建有名管道
    if (mkfifo(FIFO_PATH, 0666) == -1) {
        perror("mkfifo");
    }

    pid = fork();  // 创建子进程
    if (pid < 0) {
        perror("fork");
        return 1;
    }

    if (pid == 0) {  // 子进程
        int fd = open(FIFO_PATH, O_WRONLY);
        const char* message = "Hello from child process!";
        write(fd, message, strlen(message) + 1);
        close(fd);
    } else {  // 父进程
        int fd = open(FIFO_PATH, O_RDONLY);
        read(fd, buffer, sizeof(buffer));
        std::cout << "Parent received: " << buffer << std::endl;
        close(fd);
        unlink(FIFO_PATH);  // 删除 FIFO
    }

    return 0;
}

有名管道(FIFO)输出结果

Parent received: Hello from child process!

3. 消息队列(Message Queue)

消息队列适合于复杂的通信需求。

消息队列(Message Queue)参考代码

#include <iostream>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>

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

int main() {
    pid_t pid;
    key_t key = ftok("progfile", 65);
    int msgid = msgget(key, 0666 | IPC_CREAT);
    Message message;
    
    pid = fork(); // 创建子进程
    if (pid == 0) {  // 子进程
        message.msg_type = 1;
        strcpy(message.msg_text, "Hello from child process!");
        msgsnd(msgid, &message, sizeof(message.msg_text), 0);
    } else {  // 父进程
        msgrcv(msgid, &message, sizeof(message.msg_text), 1, 0);
        std::cout << "Parent received: " << message.msg_text << std::endl;
        msgctl(msgid, IPC_RMID, NULL);  // 删除消息队列
    }

    return 0;
}

消息队列(Message Queue)输出结果

Parent received: Hello from child process!

4. 共享内存(Shared Memory)

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

有名管道(FIFO)参考代码

#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cstring>
#include <unistd.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);
    pid_t pid;
    
    pid = fork(); // 创建子进程
    if (pid == 0) {  // 子进程
        strcpy(str, "Hello from child process!");
        shmdt(str);
    } else {  // 父进程
        sleep(1);  // 确保子进程写入完成
        std::cout << "Parent received: " << str << std::endl;
        shmdt(str);
        shmctl(shmid, IPC_RMID, NULL);  // 删除共享内存
    }

    return 0;
}

有名管道(FIFO)输出结果

Parent received: Hello from child process!

5. 信号量(Semaphore)

信号量主要用于同步。

信号量(Semaphore)参考代码

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

void semaphore_op(int semid, int op) {
    struct sembuf sop = {0, static_cast<short> (op), 0};
    semop(semid, &sop, 1);
}

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

    pid = fork();  //创建子进程
    if (pid == 0) {  // 子进程
        std::cout << "Child: Writing data...\n";
        sleep(2);
        semaphore_op(semid, 1);  // 信号量加 1
        std::cout << "Child: Data written.\n";
    } else {  // 父进程
        std::cout << "Parent: Waiting for data...\n";
        semaphore_op(semid, -1);  // 等待信号量变为 0
        std::cout << "Parent: Data received.\n";
        semctl(semid, 0, IPC_RMID);  // 删除信号量
    }

    return 0;
}

`

信号量(Semaphore)输出结果

Parent: Waiting for data...
Child: Writing data...
Child: Data written.
Parent: Data received.

6. 套接字(Socket)

适用于网络通信或本地进程间通信。

套接字(Socket)参考代码

#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstring>

int main() {
    int sv[2];  // Socket pair
    char buffer[1024];
    pid_t pid;

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
        perror("socketpair");
        return 1;
    }
    
    pid = fork(); // 创建子进程
    if (pid == 0) {  // 子进程
        close(sv[0]);
        const char* message = "Hello from child process!";
        write(sv[1], message, strlen(message) + 1);
        close(sv[1]);
    } else {  // 父进程
        close(sv[1]);
        read(sv[0], buffer, sizeof(buffer));
        std::cout << "Parent received: " << buffer << std::endl;
        close(sv[0]);
    }

    return 0;
}

套接字(Socket)输出结果

Parent received: Hello from child process!

原文地址:https://blog.csdn.net/chenmi123321/article/details/144314194

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!