您的位置:首页 > 房产 > 建筑 > linux学习:进程通信 消息队列 共享内存

linux学习:进程通信 消息队列 共享内存

2024/10/7 2:30:10 来源:https://blog.csdn.net/weixin_59669309/article/details/139400843  浏览:    关键词:linux学习:进程通信 消息队列 共享内存

目录

例子1  消息队列的创建、消息的接收、发送和队列的删除

例子2  创建消息队列,发送一条消息,接收回应消息

例子3    父进程等待子进程释放信号量才继续运行,同步

例子4    共享内存  创建共享内存段、附加到该内存、打印存储的数据,并最后分离共享内存

例子5    创建和管理共享内存,包括写入数据、等待一段时间(用于模拟数据被其他进程读取或使用的情况),最后清理共享内存资源


例子1  消息队列的创建、消息的接收、发送和队列的删除

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h> // 包含字符串处理函数库// 定义消息结构体,用于消息队列通信
struct msgbuf {long mtype;       /* 消息类型, 必须大于 0 */char mtext[256];  /* 消息数据 */
};int main()
{// 用于读取消息的结构体struct msgbuf readBuf;	key_t key;// 生成IPC键值,使用当前目录下的文件'.'和字符'm'作为输入key = ftok(".", 'm');printf("key=%x\n", key);  // 打印生成的键值,用于调试// 创建或获取消息队列,权限设置为0777,允许任何用户读写int msgId = msgget(key, IPC_CREAT | 0777);if(msgId == -1 ){printf("get queue failure\n");  // 如果消息队列创建或获取失败,输出错误消息return -1;  // 出错退出}// 清空读取缓冲区memset(&readBuf, 0, sizeof(struct msgbuf));// 从消息队列接收类型为888的消息,不使用任何特殊选项msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 888, 0);	printf("read from queue: %s\n", readBuf.mtext);  // 打印接收到的消息内容// 设置发送消息的结构体,消息类型为988,内容为"thank you for reach"struct msgbuf sendBuf = {988, "thank you for reach"};// 发送消息到消息队列msgsnd(msgId, &sendBuf, strlen(sendBuf.mtext), 0);// 删除消息队列msgctl(msgId, IPC_RMID, NULL);return 0;
}

例子2  创建消息队列,发送一条消息,接收回应消息

#include <stdio.h>      // 包含标准输入输出函数库
#include <sys/types.h>  // 包含系统数据类型定义
#include <sys/ipc.h>    // 包含IPC(进程间通信)相关的头文件
#include <sys/msg.h>    // 包含消息队列相关的函数声明和数据结构
#include <string.h>     // 包含字符串处理函数库// 定义消息结构体,用于消息队列通信
struct msgbuf {long mtype;         /* 消息类型, 必须大于 0 */char mtext[256];    /* 消息数据 */
};int main()
{struct msgbuf sendBuf = {888, "this is message from queue"};  // 发送消息的结构体struct msgbuf readBuf;  // 读取消息的结构体// 初始化读取缓冲区memset(&readBuf, 0, sizeof(struct msgbuf));// 生成IPC键值,使用当前目录下的文件'.'和字符'm'作为输入key_t key = ftok(".", 'm');printf("key=%x\n", key);  // 打印生成的键值,用于调试// 创建或获取消息队列,权限设置为0777,允许任何用户读写int msgId = msgget(key, IPC_CREAT | 0777);if(msgId == -1) {printf("get queue failure\n");return -1;  // 如果消息队列创建或获取失败,输出错误消息并退出程序}// 向消息队列发送消息msgsnd(msgId, &sendBuf, strlen(sendBuf.mtext), 0);  // 不使用任何特殊选项printf("send over\n");// 从消息队列接收类型为988的消息,不使用任何特殊选项msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 988, 0);printf("return from get: %s\n", readBuf.mtext);  // 打印接收到的消息内容// 删除消息队列msgctl(msgId, IPC_RMID, NULL);return 0;  // 程序正常结束
}

例子3    父进程等待子进程释放信号量才继续运行,同步

#include <stdio.h>   // 包含标准输入输出函数库
#include <sys/types.h>  // 包含系统数据类型定义
#include <sys/ipc.h>    // 包含IPC(进程间通信)相关的头文件
#include <sys/sem.h>    // 包含System V信号量相关的函数声明和数据结构// 为semctl定义的union,用于设置信号量的值
union semun {int              val;    /* Value for SETVAL */struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */unsigned short  *array;  /* Array for GETALL, SETALL */struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */
};// P操作函数:尝试获取信号量
void pGetKey(int id)
{struct sembuf set;set.sem_num = 0;       // 信号量编号set.sem_op = -1;       // 操作类型为减1,表示获取信号量set.sem_flg = SEM_UNDO;  // 在进程终止时撤销操作semop(id, &set, 1);    // 执行操作printf("get key\n");   // 打印获取信号量的信息
}// V操作函数:释放信号量
void vPutBackKey(int id)
{struct sembuf set;set.sem_num = 0;       // 信号量编号set.sem_op = 1;        // 操作类型为加1,表示释放信号量set.sem_flg = SEM_UNDO;  // 在进程终止时撤销操作semop(id, &set, 1);    // 执行操作printf("put back the key\n");   // 打印释放信号量的信息
}int main(int argc, char const *argv[])
{key_t key;int semid;key = ftok(".", 2);  // 生成IPC键值semid = semget(key, 1, IPC_CREAT | 0666);  // 获取或创建一个信号量union semun initsem;initsem.val = 0;semctl(semid, 0, SETVAL, initsem);  // 初始化信号量的值为0int pid = fork();  // 创建子进程if(pid > 0){// 父进程pGetKey(semid);  // 获取信号量printf("this is father\n");vPutBackKey(semid);  // 释放信号量semctl(semid, 0, IPC_RMID, NULL);  // 删除信号量}else if(pid == 0){// 子进程printf("this is child\n");vPutBackKey(semid);  // 释放信号量}else{// fork失败printf("fork error\n");}            return 0;
}

例子4    共享内存  创建共享内存段、附加到该内存、打印存储的数据,并最后分离共享内存

#include <sys/ipc.h>   // 包含IPC标准头文件,用于键值的生成等
#include <sys/shm.h>   // 包含System V共享内存功能相关的头文件
#include <stdlib.h>    // 包含标准库函数,如exit
#include <stdio.h>     // 包含标准输入输出函数
#include <string.h>    // 包含字符串处理函数int main()
{int shmid;  // 共享内存标识符char *shmaddr;  // 指向共享内存的指针key_t key;  // IPC键key = ftok(".", 1);  // 使用ftok生成一个唯一键值,当前目录作为路径,1作为项目标识符// 请求访问键值为key的共享内存,大小为4096字节(1024*4),权限标志为0(只获取不创建)shmid = shmget(key, 1024 * 4, 0);if (shmid == -1) {printf("shmget noOk\n");  // 如果获取共享内存失败,打印错误消息exit(-1);  // 退出程序}// 将共享内存附加到进程的地址空间shmaddr = shmat(shmid, 0, 0);  // 第二个参数是指定内存附加到进程空间的地址(0表示系统选择)if (shmaddr == (void*) -1) {printf("shmat error\n");  // 附加失败exit(-1);}printf("shmat ok\n");  // 打印附加成功消息printf("data: %s\n", shmaddr);  // 打印共享内存中的数据// 将共享内存从当前进程的地址空间分离shmdt(shmaddr);printf("quit\n");  // 打印退出消息return 0;  // 正常退出程序
}

例子5    创建和管理共享内存,包括写入数据、等待一段时间(用于模拟数据被其他进程读取或使用的情况),最后清理共享内存资源

#include <sys/ipc.h>   // 包含IPC标准头文件,用于键值的生成等
#include <sys/shm.h>   // 包含System V共享内存功能相关的头文件
#include <stdlib.h>    // 包含标准库函数,如exit
#include <stdio.h>     // 包含标准输入输出函数
#include <string.h>    // 包含字符串处理函数
#include <unistd.h>    // 包含常用的系统调用函数,如sleepint main()
{int shmid;  // 共享内存标识符char *shmaddr;  // 指向共享内存的指针key_t key;  // IPC键key = ftok(".", 1);  // 使用ftok生成一个唯一键值,当前目录作为路径,1作为项目标识符// 创建共享内存,大小为4KB,权限设置为0666,并设置IPC_CREAT标志以确保如果不存在则创建shmid = shmget(key, 1024 * 4, IPC_CREAT | 0666);if (shmid == -1) {printf("shmget noOk\n");  // 如果获取共享内存失败,打印错误消息exit(-1);  // 退出程序}// 将共享内存附加到进程的地址空间shmaddr = shmat(shmid, 0, 0);  // 第二个参数是指定内存附加到进程空间的地址(0表示系统选择)if (shmaddr == (void *) -1) {printf("shmat error\n");  // 附加失败exit(-1);}printf("shmat ok\n");  // 打印附加成功消息// 将字符串 "chenlichen" 复制到共享内存中strcpy(shmaddr, "helloworld");// 休眠5秒,模拟等待其他进程/线程读取或操作这段共享内存sleep(5);// 将共享内存从当前进程的地址空间分离shmdt(shmaddr);// 删除共享内存段shmctl(shmid, IPC_RMID, 0);printf("quit\n");  // 打印退出消息return 0;  // 程序正常结束
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com