kimi写代码:内核消息队列

处理msgrcv返回E2BIG

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

typedef struct {
    long mtype;
    char mtext[1024]; // 假设消息文本的最大长度为1024字节
} message;

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

    message msg;
    ssize_t msglen = 0;
    while ((msglen = msgrcv(msqid, &msg, sizeof(msg.mtext), 1, MSG_NOERROR)) == -1) {
        if (errno == E2BIG) {
            fprintf(stderr, "Buffer too small, resizing...\n");
            // 这里可以调整缓冲区大小,例如,可以增加mtext的大小
            // 然后重新尝试接收消息
        } else {
            perror("msgrcv");
            break;
        }
    }

    if (msglen > 0) {
        printf("Received message of type %ld with size %zd\n", msg.mtype, msglen);
        // 处理接收到的消息
    }

    // 清理资源
    if (msgctl(msqid, IPC_RMID, NULL) == -1) {
        perror("msgctl");
    }

    return 0;
}

如何防止持有内核消息队列的进程被信号杀死后内核消息队列资源泄露?

在 Linux 系统中,内核消息队列是进程间通信的一种方式,通常用于进程间传递消息。当一个持有内核消息队列的进程被信号杀死时,可能会导致消息队列资源泄露。为了解决这个问题,可以采取以下一些措施:

  • 使用信号处理程序:
    为进程设置信号处理程序,当接收到终止信号(如 SIGTERM 或 SIGINT)时,先清理消息队列资源再退出。例如:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgid;

void cleanup(int sig) {
    if (msgctl(msgid, IPC_RMID, NULL) == -1) {
        perror("msgctl");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

int main() {
    struct sigaction sa;
    sa.sa_handler = cleanup;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGTERM, &sa, NULL) == -1) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }
    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    // 创建消息队列
    key_t key = ftok("/tmp", 'a');
    msgid = msgget(key, 0666 | IPC_CREAT);
    if (msgid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    // 程序的其他部分

    pause(); // 等待信号
    return 0;
}
  • 使用守护进程:
    将程序运行为守护进程,这样它可以在后台运行,并在接收到终止信号时清理资源。守护进程通常在启动时注册信号处理程序。

  • 使用 atexit 函数:
    在 C 程序中,可以使用 atexit 函数注册一个函数,该函数在程序退出时被调用。这可以确保在程序退出时清理消息队列资源:

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

int msgid;

void cleanup(void) {
    if (msgctl(msgid, IPC_RMID, NULL) == -1) {
        perror("msgctl");
        exit(EXIT_FAILURE);
    }
}

int main() {
    key_t key = ftok("/tmp", 'a');
    msgid = msgget(key, 0666 | IPC_CREAT);
    if (msgid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    atexit(cleanup);

    // 程序的其他部分

    pause(); // 等待信号
    return 0;
}
posted @ 2024-07-18 10:02  joel-q  阅读(10)  评论(0编辑  收藏  举报