面试题答案
一键面试- 系统处理相同优先级消息的方式:
- 在Linux消息队列中,当多个消息具有相同优先级时,系统通常按照“先进先出”(FIFO)的原则处理。即先发送到消息队列的消息会先被接收。这是由Linux消息队列的底层实现机制决定的,它维护了一个队列结构,在同一优先级内,新消息被追加到队列尾部,接收时从队列头部获取消息。
- 手动干预相同优先级消息处理顺序的代码实现:
- 方法一:自定义消息结构并排序:
- 可以在消息结构体中添加一个额外的字段,例如时间戳或者自定义的序号。
- 以下是一个简单示例代码:
- 方法一:自定义消息结构并排序:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <time.h>
#define MSG_SIZE 128
// 自定义消息结构,添加时间戳字段
typedef struct {
long mtype;
char mtext[MSG_SIZE];
time_t timestamp;
} MyMsgType;
// 比较函数,用于qsort排序,按照时间戳从小到大排序
int compare(const void *a, const void *b) {
MyMsgType *msgA = (MyMsgType *)a;
MyMsgType *msgB = (MyMsgType *)b;
return (int)(msgA->timestamp - msgB->timestamp);
}
int main() {
key_t key;
int msgid;
MyMsgType msg;
MyMsgType msgs[10]; // 假设最多存储10个消息
int msg_count = 0;
// 生成唯一键值
key = ftok(".", 'a');
if (key == -1) {
perror("ftok");
return 1;
}
// 创建消息队列
msgid = msgget(key, IPC_CREAT | 0666);
if (msgid == -1) {
perror("msgget");
return 1;
}
// 接收消息并存储到数组
while (1) {
if (msgrcv(msgid, &msg, MSG_SIZE, 0, IPC_NOWAIT) != -1) {
msg.timestamp = time(NULL);
msgs[msg_count++] = msg;
} else {
break;
}
}
// 对消息按照时间戳排序
qsort(msgs, msg_count, sizeof(MyMsgType), compare);
// 重新发送消息,按照自定义顺序
for (int i = 0; i < msg_count; i++) {
if (msgsnd(msgid, &msgs[i], MSG_SIZE, 0) == -1) {
perror("msgsnd");
return 1;
}
}
// 接收消息,此时消息顺序已被干预
for (int i = 0; i < msg_count; i++) {
if (msgrcv(msgid, &msg, MSG_SIZE, 0, 0) == -1) {
perror("msgrcv");
return 1;
}
printf("Received message: %s\n", msg.mtext);
}
// 删除消息队列
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("msgctl");
return 1;
}
return 0;
}
- 方法二:在发送消息时添加自定义序号:
- 在消息结构体中添加一个序号字段。发送消息时,为每个消息分配一个递增的序号。接收消息后,根据序号对消息进行排序,然后再按照期望的顺序处理。这种方式与上述时间戳类似,只是使用序号来标记消息顺序。
- 方法三:使用多个消息队列:
- 可以创建多个消息队列,例如按照某种规则(如消息的部分内容或者其他条件)将相同优先级的消息发送到不同的队列。接收时,按照期望的顺序从不同队列中获取消息。这样可以通过队列的选择来手动干预消息处理顺序。例如:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define MSG_SIZE 128
// 自定义消息结构
typedef struct {
long mtype;
char mtext[MSG_SIZE];
} MyMsgType;
int main() {
key_t key1, key2;
int msgid1, msgid2;
MyMsgType msg;
// 生成两个不同的键值
key1 = ftok(".", 'a');
key2 = ftok(".", 'b');
if (key1 == -1 || key2 == -1) {
perror("ftok");
return 1;
}
// 创建两个消息队列
msgid1 = msgget(key1, IPC_CREAT | 0666);
msgid2 = msgget(key2, IPC_CREAT | 0666);
if (msgid1 == -1 || msgid2 == -1) {
perror("msgget");
return 1;
}
// 发送消息到不同队列,假设根据消息内容首字母判断
char message1[] = "Apple";
char message2[] = "Banana";
msg.mtype = 1;
if (message1[0] < message2[0]) {
strcpy(msg.mtext, message1);
if (msgsnd(msgid1, &msg, MSG_SIZE, 0) == -1) {
perror("msgsnd");
return 1;
}
strcpy(msg.mtext, message2);
if (msgsnd(msgid2, &msg, MSG_SIZE, 0) == -1) {
perror("msgsnd");
return 1;
}
} else {
strcpy(msg.mtext, message2);
if (msgsnd(msgid1, &msg, MSG_SIZE, 0) == -1) {
perror("msgsnd");
return 1;
}
strcpy(msg.mtext, message1);
if (msgsnd(msgid2, &msg, MSG_SIZE, 0) == -1) {
perror("msgsnd");
return 1;
}
}
// 按照期望顺序接收消息
if (msgrcv(msgid1, &msg, MSG_SIZE, 1, 0) == -1) {
perror("msgrcv");
return 1;
}
printf("Received from msgid1: %s\n", msg.mtext);
if (msgrcv(msgid2, &msg, MSG_SIZE, 1, 0) == -1) {
perror("msgrcv");
return 1;
}
printf("Received from msgid2: %s\n", msg.mtext);
// 删除消息队列
if (msgctl(msgid1, IPC_RMID, NULL) == -1) {
perror("msgctl");
return 1;
}
if (msgctl(msgid2, IPC_RMID, NULL) == -1) {
perror("msgctl");
return 1;
}
return 0;
}
通过以上方法,可以手动干预相同优先级消息在Linux消息队列中的处理顺序。