史啦啦 的學生作業(yè):
【圖片】
#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 // 消息最大長度
// 消息結(jié)構體(必須包含long類型作為首成員)
struct msgbuf {
long mtype; // 消息類型標識
char mtext[MSG_SIZE]; // 消息內(nèi)容
};
// 子進程消息接收函數(shù)
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);
}
// 持續(xù)接收指定類型的消息
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;
// 創(chuàng)建IPC鍵值
if ((key = ftok(PATHNAME, PROJ_ID)) == -1) {
perror("[PARENT] ftok failed");
exit(EXIT_FAILURE);
}
// 創(chuàng)建消息隊列(IPC_CREAT表示不存在則創(chuàng)建)
if ((msgid = msgget(key, IPC_CREAT | 0666)) == -1) {
perror("[PARENT] msgget failed");
exit(EXIT_FAILURE);
}
// 創(chuàng)建子進程A
if ((pid_a = fork()) == 0) {
child_process(MSG_TYPE_A); // 處理類型100的消息
}
// 創(chuàng)建子進程B
if ((pid_b = fork()) == 0) {
child_process(MSG_TYPE_B); // 處理類型200的消息
}
// 父進程消息發(fā)送邏輯
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;
// 發(fā)送退出信號給子進程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");
}
// 發(fā)送退出信號給子進程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;
}
// 發(fā)送消息到隊列
if (msgsnd(msgid, &msg, strlen(msg.mtext)+1, 0) == -1) {
perror("[PARENT] msgsnd failed");
}
}
// 等待子進程結(jié)束
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] 系統(tǒng)已清理\n");
return EXIT_SUCCESS;
}