MST

星途 面试题库

面试题:C语言Linux消息队列清空的多场景处理

假设你正在开发一个多进程应用程序,多个进程会向同一个消息队列发送和读取消息。现在需要在特定条件下清空消息队列,描述如何设计代码以确保在清空操作时不会影响其他进程正常的消息收发,且不会出现数据丢失或竞争条件,用C语言伪代码示例说明关键部分。
31.1万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
  1. 总体思路
    • 使用信号量来协调进程间对消息队列的操作。
    • 清空操作前获取信号量,完成后释放信号量,这样可以防止其他进程在清空操作时进行消息收发,避免数据丢失和竞争条件。
  2. C语言伪代码示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <string.h>

// 消息结构体
typedef struct msgbuf {
    long mtype;
    char mtext[256];
} message_buf;

// 信号量操作函数
union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

// 初始化信号量
int init_semaphore(int semid, int value) {
    union semun arg;
    arg.val = value;
    if (semctl(semid, 0, SETVAL, arg) == -1) {
        perror("semctl SETVAL");
        return -1;
    }
    return 0;
}

// 获取信号量
int acquire_semaphore(int semid) {
    struct sembuf sops[1];
    sops[0].sem_num = 0;
    sops[0].sem_op = -1;
    sops[0].sem_flg = SEM_UNDO;
    if (semop(semid, sops, 1) == -1) {
        perror("semop acquire");
        return -1;
    }
    return 0;
}

// 释放信号量
int release_semaphore(int semid) {
    struct sembuf sops[1];
    sops[0].sem_num = 0;
    sops[0].sem_op = 1;
    sops[0].sem_flg = SEM_UNDO;
    if (semop(semid, sops, 1) == -1) {
        perror("semop release");
        return -1;
    }
    return 0;
}

// 清空消息队列
void clear_message_queue(int msqid) {
    message_buf msg;
    while (msgrcv(msqid, &msg, sizeof(msg.mtext), 0, IPC_NOWAIT)!= -1);
}

int main() {
    key_t key;
    int msqid, semid;

    // 生成唯一键值
    key = ftok(".", 'a');
    if (key == -1) {
        perror("ftok");
        return 1;
    }

    // 创建消息队列
    msqid = msgget(key, IPC_CREAT | 0666);
    if (msqid == -1) {
        perror("msgget");
        return 1;
    }

    // 创建信号量
    semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1) {
        perror("semget");
        return 1;
    }

    // 初始化信号量
    if (init_semaphore(semid, 1) == -1) {
        return 1;
    }

    // 假设满足特定条件,清空消息队列
    if (specific_condition) {
        if (acquire_semaphore(semid) == -1) {
            return 1;
        }
        clear_message_queue(msqid);
        if (release_semaphore(semid) == -1) {
            return 1;
        }
    }

    // 其他进程的消息发送和接收代码,这里省略

    // 删除消息队列和信号量
    if (msgctl(msqid, IPC_RMID, NULL) == -1) {
        perror("msgctl IPC_RMID");
        return 1;
    }
    if (semctl(semid, 0, IPC_RMID) == -1) {
        perror("semctl IPC_RMID");
        return 1;
    }

    return 0;
}

上述伪代码中:

  • init_semaphore 函数用于初始化信号量。
  • acquire_semaphore 函数用于获取信号量,以阻止其他进程操作消息队列。
  • release_semaphore 函数用于释放信号量,允许其他进程继续操作消息队列。
  • clear_message_queue 函数在获取信号量后,循环从消息队列中读取消息直到队列为空,实现清空操作。
  • main 函数中,假设满足 specific_condition 条件时,进行清空消息队列的操作,通过信号量确保操作的原子性,避免数据丢失和竞争条件。