面试题答案
一键面试- 总体思路:
- 使用信号量来协调进程间对消息队列的操作。
- 清空操作前获取信号量,完成后释放信号量,这样可以防止其他进程在清空操作时进行消息收发,避免数据丢失和竞争条件。
- 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
条件时,进行清空消息队列的操作,通过信号量确保操作的原子性,避免数据丢失和竞争条件。