进程之间的通信方式有哪些?(附代码帮助理解)

通信方法优点缺点
管道(Pipes)实现简单,适用于父子进程通信单向通信,不适合双向通信;不适合大数据量传输;通信效率较低
信号(Signals)异步通信,可以在任何时刻通知进程通信内容受限,主要用于进程间的同步和控制
消息队列支持异步处理,可以进行数据存储通信不及时,数据大小有限制
共享内存通信效率高,适合大量数据传输需要同步机制以防数据冲突,可能导致地址冲突
信号量用于进程间同步和互斥控制不当使用易造成死锁
套接字(Sockets)适用于网络通信,支持不同主机间的进程通信通信开销较大
内存映射文件可以实现高效的共享内存通信,减少数据拷贝开销需要同步机制,管理复杂

1.管道(Pipes)

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    int fd[2]; // 文件描述符数组
    pid_t pid;

    if (pipe(fd) == -1) {
        perror("Pipe");
        return 1;
    }

    pid = fork();
    if (pid < 0) {
        perror("Fork");
        return 1;
    }

    if (pid == 0) { // 子进程
        close(fd); // 关闭读端
        write(fd[1], "Hello, World!", 13);
        close(fd[1]);
    } else { // 父进程
        close(fd[1]); // 关闭写端
        char msg[100];
        read(fd, msg, sizeof(msg) - 1);
        msg[sizeof(msg) - 1] = '\0'; // 确保字符串以null结束
        printf("Parent received: %s\n", msg);
        close(fd);
    }

    wait(NULL); // 等待子进程结束
    return 0;
}

2. 信号(Signals)

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

void handler(int sig) {
    printf("Caught signal %d\n", sig);
}

int main() {
    signal(SIGINT, handler); // 注册信号处理器
    while(1);
    return 0;
}

3. 消息队列

#include <sys/msg.h>
#include <stdio.h>
#include <string.h>

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

int main() {
    key_t key = ftok(".", 'M');
    int msqid = msgget(key, 0666 | IPC_CREAT);
    if (msqid == -1) {
        perror("msgget");
        return 1;
    }

    struct my_msgbuf msg;
    msg.mtype = 1;
    strcpy(msg.mtext, "Hello, Message queue!");

    if (msgsnd(msqid, &msg, strlen(msg.mtext) + 1, 0) == -1) {
        perror("msgsnd");
        return 1;
    }

    if (msgrcv(msqid, &msg, sizeof(msg.mtext), 1, 0) == -1) {
        perror("msgrcv");
        return 1;
    }

    printf("Received message: %s\n", msg.mtext);

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

4. 共享内存

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

int main() {
    key_t key = ftok(".", 'S');
    int shmid = shmget(key, 100, 0666 | IPC_CREAT);
    char *data = shmat(shmid, NULL, 0);
    strcpy(data, "Hello, Shared Memory!");

    printf("Data in shared memory: %s\n", data);

    shmdt(data);
    shmctl(shmid, IPC_RMID, 0);
    return 0;
}

5. 信号量

#include <iostream>
#include <semaphore.h>
#include <thread>
#include <chrono>

sem_t sem; // POSIX semaphore

void increment() {
    sem_wait(&sem); // 等待信号量
    std::cout << "Resource accessed by thread " << std::this_thread::get_id() << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    sem_post(&sem); // 释放信号量
}

int main() {
    if (sem_init(&sem, 0, 1) == -1) {
        std::cerr << "Semaphore initialization failed" << std::endl;
        return 1;
    }

    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    sem_destroy(&sem); // 销毁信号量
    return 0;
}

6.套接字(Sockets)

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

void handle_client(int client_socket) {
    char buffer[1024];
    memset(buffer, '\0', sizeof(buffer));
    int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
    if (bytes_received > 0) {
        std::cout << "Received: " << buffer << std::endl;
        send(client_socket, "Hello, Client!", 15, 0);
    }
    close(client_socket);
}

int main() {
    int listen_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_socket == -1) {
        std::cerr << "Socket creation failed" << std::endl;
        return 1;
    }

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(listen_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        std::cerr << "Binding failed" << std::endl;
        return 1;
    }

    if (listen(listen_socket, 5) == -1) {
        std::cerr << "Listening failed" << std::endl;
        return 1;
    }

    while (true) {
        struct sockaddr_in client_addr;
        socklen_t addr_len = sizeof(client_addr);
        int client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &addr_len);
        if (client_socket != -1) {
            std::cout << "New client connected" << std::endl;
            std::thread(handle_client, client_socket).detach();
        }
    }

    close(listen_socket);
    return 0;
}

7.内存映射文件

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

int main() {
    int file_desc = open("testfile", O_RDWR|O_CREAT, 0644);
    if (file_desc == -1) {
        std::cerr << "File opening failed" << std::endl;
        return 1;
    }

    if (ftruncate(file_desc, 100) == -1) {
        std::cerr << "File truncation failed" << std::endl;
        return 1;
    }

    char *data = (char *)mmap(NULL, 100, PROT_READ|PROT_WRITE, MAP_SHARED, file_desc, 0);
    if (data == MAP_FAILED) {
        std::cerr << "Memory mapping failed" << std::endl;
        return 1;
    }

    strcpy(data, "Hello, Memory Mapped File!");

    munmap(data, 100);
    close(file_desc);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值