本文主要是介绍8.29练习,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
进程间通信示例
使用消息队列在两个独立的 C 程序之间进行进程间通信。每个程序都包含父进程和子进程,父进程用于写消息到消息队列,子进程用于从消息队列读取消息。
程序1 (s1.c)
#include <myhead.h> // 定义消息缓冲区结构体
struct msgbuf {long mtype; // 消息类型char mtext[1000]; // 消息正文
};#define LENG (sizeof(struct msgbuf) - sizeof(long)) // 计算消息正文的长度int main() {key_t key1 = ftok("./", 'A'); // 创建key值1key_t key2 = ftok("./", 'B'); // 创建key值2if (key1 == -1 || key2 == -1) {perror("ftok"); return -1;}int msgID1 = msgget(key1, IPC_CREAT | 0664); // 创建或获取消息队列1int msgID2 = msgget(key2, IPC_CREAT | 0664); // 创建或获取消息队列2if (msgID1 == -1 || msgID2 == -1) {perror("msgget"); return -1;}pid_t pid = fork(); // 创建子进程if (pid > 0) {// 父进程发送消息到队列1struct msgbuf send;while (1) {printf("s1父进程:请输入消息类型:\n");scanf("%ld", &send.mtype); // 读取消息类型getchar(); // 清除输入缓冲区中的换行符printf("s1父进程:请输入消息的内容:\n");fgets(send.mtext, sizeof(send.mtext), stdin); // 读取消息内容send.mtext[strlen(send.mtext) - 1] = '\0'; // 去掉换行符msgsnd(msgID1, &send, LENG, 0); // 发送消息到队列1printf("s1父进程:发送消息:类型=%ld,内容=%s\n", send.mtype, send.mtext);if (strcmp(send.mtext, "quit") == 0) { // 如果消息内容是"quit",则退出循环break;}}// 等待子进程结束wait(NULL);// 删除消息队列1if (msgctl(msgID1, IPC_RMID, NULL) == -1) {perror("msgctl"); return -1;}printf("s1父进程:消息队列1已删除\n");} else if (pid == 0) {// 子进程读取消息从队列2struct msgbuf rcv;while (1) {msgrcv(msgID2, &rcv, LENG, 0, 0); // 从队列2读取消息,第一个0:读取第一个信息不论类型,第二个0:阻塞接收printf("s1子进程:收到消息:类型=%ld,内容=%s\n", rcv.mtype, rcv.mtext);if (strcmp(rcv.mtext, "quit") == 0) { // 如果消息内容是"quit",则退出循环break;}}printf("s1子进程:退出\n");exit(0); // 子进程退出} else {perror("fork"); return -1;}return 0;
}
程序2 (s2.c)
#include <myhead.h> // 包含自定义头文件
// 定义消息缓冲区结构体
struct msgbuf {long mtype; // 消息类型char mtext[1000]; // 消息正文
};#define LENG (sizeof(struct msgbuf) - sizeof(long)) // 计算消息正文的长度int main() {key_t key1 = ftok("./", 'A'); // 创建key值1key_t key2 = ftok("./", 'B'); // 创建key值2if (key1 == -1 || key2 == -1) {perror("ftok"); return -1;}int msgID1 = msgget(key1, IPC_CREAT | 0664); // 创建或获取消息队列1int msgID2 = msgget(key2, IPC_CREAT | 0664); // 创建或获取消息队列2if (msgID1 == -1 || msgID2 == -1) {perror("msgget"); return -1;}pid_t pid = fork(); // 创建子进程if (pid > 0) {// 父进程发送消息到队列2struct msgbuf send;while (1) {printf("s2父进程:请输入消息类型:\n");scanf("%ld", &send.mtype); // 读取消息类型getchar(); // 清除输入缓冲区中的换行符printf("s2父进程:请输入消息的内容:\n");fgets(send.mtext, sizeof(send.mtext), stdin); // 读取消息内容send.mtext[strlen(send.mtext) - 1] = '\0'; // 去掉换行符msgsnd(msgID2, &send, LENG, 0); // 发送消息到队列2printf("s2父进程:发送消息:类型=%ld,内容=%s\n", send.mtype, send.mtext);if (strcmp(send.mtext, "quit") == 0) { // 如果消息内容是"quit",则退出循环break;}}// 等待子进程结束wait(NULL);// 删除消息队列2if (msgctl(msgID2, IPC_RMID, NULL) == -1) {perror("msgctl"); return -1;}printf("s2父进程:消息队列2已删除\n");} else if (pid == 0) {// 子进程读取消息从队列1struct msgbuf rcv;while (1) {msgrcv(msgID1, &rcv, LENG, 0, 0); // 从队列1读取消息,第一个0:读取第一个信息不论类型,第二个0:阻塞接收printf("s2子进程:收到消息:类型=%ld,内容=%s\n", rcv.mtype, rcv.mtext);if (strcmp(rcv.mtext, "quit") == 0) { // 如果消息内容是"quit",则退出循环break;}}printf("s2子进程:退出\n");exit(0); // 子进程退出} else {perror("fork"); return -1;}return 0;
}
解释
-
定义消息缓冲区结构体:
struct msgbuf {long mtype; // 消息类型char mtext[1000]; // 消息正文 };
-
计算消息正文的长度:
#define LENG (sizeof(struct msgbuf) - sizeof(long))
-
主函数:
- 使用
ftok
生成两个唯一的键值。 - 使用
msgget
创建或获取两个消息队列。 - 使用
fork
创建子进程。
- 使用
-
父进程发送消息:
- 父进程负责发送消息到消息队列。
- 循环读取用户输入的消息类型和消息正文,并发送到消息队列。
- 如果消息正文是 “quit”,则退出循环并等待子进程结束。
- 删除消息队列。
-
子进程读取消息:
- 子进程负责从消息队列中读取消息。
- 循环接收消息队列中的消息,并打印消息类型和消息正文。
- 如果消息正文是 “quit”,则退出循环。
这两个程序,每个程序都包含父进程和子进程,父进程用于写消息到消息队列,子进程用于从消息队列中读取消息,实现了两个程序之间的进程间通信。
这篇关于8.29练习的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!