📜  Ubuntu-消息传递(1)

📅  最后修改于: 2023-12-03 15:20:47.037000             🧑  作者: Mango

Ubuntu 消息传递

Ubuntu 是一种基于 Linux 内核的操作系统,它支持消息传递机制,这使得不同进程之间可以安全,高效地发送消息来实现进程间通信。

消息传递

消息传递是一种进程间通信的方式,它允许不同进程之间传递数据和控制信息。发送进程将消息发送给接收进程,接收进程通过接收消息来处理它们。消息传递机制可以保证不同进程间的隔离性,从而实现更加高效和安全的进程间通信。

在 Ubuntu 中,消息传递机制由 System V IPC 和 POSIX 消息队列(POSIX MQ)两种机制组成。System V IPC 提供了共享内存、消息队列和信号量三种机制,而 POSIX MQ 则只提供了消息队列。

System V IPC
共享内存

共享内存是 System V IPC 机制中的一种,它允许多个进程共享同一段物理内存,从而实现数据共享。使用共享内存时,需要先创建或访问一个共享内存区域,并将其附加到进程的地址空间中。每一个共享内存区域都有一个关联的标识符,可以使用该标识符来找到共享内存区域。

以下是使用共享内存的一个例子:

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

int main() {
    // 创建共享内存区域
    int shmid = shmget(IPC_PRIVATE, 1024, 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    // 将共享内存区域附加到进程地址空间中
    void *shmaddr = shmat(shmid, NULL, 0);
    if (shmaddr == (void *) -1) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    // 向共享内存区域中写入数据
    sprintf((char *) shmaddr, "Hello, shared memory!");

    // 分离共享内存区域
    shmdt(shmaddr);

    return 0;
}
消息队列

消息队列是 System V IPC 机制中的另一种,它允许进程向一个队列中发送消息,并从队列中接收消息。消息队列也有一个关联的标识符,可以使用该标识符来找到消息队列。

以下是使用消息队列的一个例子:

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

struct message {
    long type;
    char text[1024];
};

int main() {
    // 创建消息队列
    int msgid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
    if (msgid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    // 发送消息
    struct message msg = {1, "Hello, message queue!"};
    if (msgsnd(msgid, &msg, sizeof(msg.text), 0) == -1) {
        perror("msgsnd");
        exit(EXIT_FAILURE);
    }

    // 接收消息
    memset(&msg, 0, sizeof(msg));
    if (msgrcv(msgid, &msg, sizeof(msg.text), 0, 0) == -1) {
        perror("msgrcv");
        exit(EXIT_FAILURE);
    }
    printf("%s\n", msg.text);

    // 删除消息队列
    if (msgctl(msgid, IPC_RMID, NULL) == -1) {
        perror("msgctl");
        exit(EXIT_FAILURE);
    }

    return 0;
}
信号量

信号量也是 System V IPC 机制中的一种,它可以用来控制进程对共享资源的访问。每个共享资源都有一个关联的信号量,进程可以通过执行 P 操作和 V 操作来获取和释放该信号量。在信号量计数器大于 0 时,P 操作将信号量计数器减 1,并立即返回;在信号量计数器等于 0 时,P 操作将阻塞并等待信号量计数器的值变为正数。类似地,V 操作将信号量计数器加 1。

以下是使用信号量的一个例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>

int main() {
    // 创建信号量
    int semid = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
    if (semid == -1) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    // 初始化信号量计数器为 1
    if (semctl(semid, 0, SETVAL, 1) == -1) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }

    // 执行 P 操作
    struct sembuf sops = {0, -1, 0};
    if (semop(semid, &sops, 1) == -1) {
        perror("semop");
        exit(EXIT_FAILURE);
    }

    // 执行 V 操作
    sops.sem_op = 1;
    if (semop(semid, &sops, 1) == -1) {
        perror("semop");
        exit(EXIT_FAILURE);
    }

    // 删除信号量
    if (semctl(semid, 0, IPC_RMID) == -1) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }

    return 0;
}
POSIX 消息队列

在 Ubuntu 中,使用 POSIX 消息队列的方式与 System V IPC 类似。以下是使用 POSIX 消息队列的一个例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <mqueue.h>

int main() {
    // 创建消息队列
    mqd_t mqd = mq_open("/test", O_RDWR | O_CREAT, 0666, NULL);
    if (mqd == (mqd_t) -1) {
        perror("mq_open");
        exit(EXIT_FAILURE);
    }

    // 发送消息
    if (mq_send(mqd, "Hello, POSIX message queue!", strlen("Hello, POSIX message queue!"), 0) == -1) {
        perror("mq_send");
        exit(EXIT_FAILURE);
    }

    // 接收消息
    char buf[1024];
    memset(buf, 0, sizeof(buf));
    if (mq_receive(mqd, buf, sizeof(buf), NULL) == -1) {
        perror("mq_receive");
        exit(EXIT_FAILURE);
    }
    printf("%s\n", buf);

    // 删除消息队列
    if (mq_close(mqd) == -1) {
        perror("mq_close");
        exit(EXIT_FAILURE);
    }
    if (mq_unlink("/test") == -1) {
        perror("mq_unlink");
        exit(EXIT_FAILURE);
    }

    return 0;
}
总结

Ubuntu 中提供了多种进程间通信的方式,其中消息传递机制是一种常用的方式。使用 System V IPC 和 POSIX 消息队列,开发者可以轻松实现进程间通信,提升了程序的可扩展性和高并发性。