史啦啦 的学生作业:
【图片】
#include
#include
#include
#include
#include
#include
#include
#include
#define PATHNAME "." // 用于生成IPC键值的路径
#define PROJ_ID 88 // 项目ID
#define MSG_TYPE_A 100 // 子进程A的消息类型
#define MSG_TYPE_B 200 // 子进程B的消息类型
#define MSG_SIZE 1024 // 消息最大长度
// 消息结构体(必须包含long类型作为首成员)
struct msgbuf {
long mtype; // 消息类型标识
char mtext[MSG_SIZE]; // 消息内容
};
// 子进程消息接收函数
void child_process(int msg_type) {
int msgid;
key_t key;
// 生成相同的IPC键值
if ((key = ftok(PATHNAME, PROJ_ID)) == -1) {
perror("[CHILD] ftok failed");
exit(EXIT_FAILURE);
}
// 获取消息队列
if ((msgid = msgget(key, 0666)) == -1) {
perror("[CHILD] msgget failed");
exit(EXIT_FAILURE);
}
// 持续接收指定类型的消息
while (1) {
struct msgbuf msg;
ssize_t ret = msgrcv(msgid, &msg, sizeof(msg.mtext), msg_type, 0);
if (ret == -1) {
perror("[CHILD] msgrcv failed");
exit(EXIT_FAILURE);
}
// 收到退出指令
if (strcmp(msg.mtext, "quit") == 0) {
printf("[CHILD %d] Received exit signal\n", msg_type);
break;
}
printf("[CHILD %d] Received: %s\n", msg_type, msg.mtext);
}
exit(EXIT_SUCCESS);
}
int main() {
key_t key;
int msgid;
pid_t pid_a, pid_b;
// 创建IPC键值
if ((key = ftok(PATHNAME, PROJ_ID)) == -1) {
perror("[PARENT] ftok failed");
exit(EXIT_FAILURE);
}
// 创建消息队列(IPC_CREAT表示不存在则创建)
if ((msgid = msgget(key, IPC_CREAT | 0666)) == -1) {
perror("[PARENT] msgget failed");
exit(EXIT_FAILURE);
}
// 创建子进程A
if ((pid_a = fork()) == 0) {
child_process(MSG_TYPE_A); // 处理类型100的消息
}
// 创建子进程B
if ((pid_b = fork()) == 0) {
child_process(MSG_TYPE_B); // 处理类型200的消息
}
// 父进程消息发送逻辑
char input[MSG_SIZE];
while (1) {
printf("[PARENT] Input (格式 A/B message 或 quit): ");
fgets(input, MSG_SIZE, stdin);
input[strcspn(input, "\n")] = '\0'; // 去除换行符
// 退出处理
if (strcmp(input, "quit") == 0) {
struct msgbuf quit_msg;
// 发送退出信号给子进程A
quit_msg.mtype = MSG_TYPE_A;
strcpy(quit_msg.mtext, "quit");
if (msgsnd(msgid, &quit_msg, strlen(quit_msg.mtext)+1, 0) == -1) {
perror("[PARENT] msgsnd quit failed");
}
// 发送退出信号给子进程B
quit_msg.mtype = MSG_TYPE_B;
if (msgsnd(msgid, &quit_msg, strlen(quit_msg.mtext)+1, 0) == -1) {
perror("[PARENT] msgsnd quit failed");
}
break;
}
// 消息格式解析
struct msgbuf msg;
if (strncmp(input, "A ", 2) == 0) {
msg.mtype = MSG_TYPE_A;
strcpy(msg.mtext, input+2);
} else if (strncmp(input, "B ", 2) == 0) {
msg.mtype = MSG_TYPE_B;
strcpy(msg.mtext, input+2);
} else {
printf("[PARENT] 无效格式,示例: A Hello 或 B World\n");
continue;
}
// 发送消息到队列
if (msgsnd(msgid, &msg, strlen(msg.mtext)+1, 0) == -1) {
perror("[PARENT] msgsnd failed");
}
}
// 等待子进程结束
waitpid(pid_a, NULL, 0);
waitpid(pid_b, NULL, 0);
// 清理消息队列
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("[PARENT] msgctl failed");
exit(EXIT_FAILURE);
}
printf("[PARENT] 系统已清理\n");
return EXIT_SUCCESS;
}