【ARM&Linux】共享内存的使用

2019-07-12 20:16发布

class="markdown_views prism-atelier-sulphurpool-light">

《LINUX系统下共享内存的编程代码笔记》


【代码&说明】

/**************************************************************************************** * 文件名: write.c * 创建者: * 时 间: * 联 系: * 简 介: 共享内存编程实验代码,参考文档《unix环境高级编程》 *****************************************************************************************/ /*********************************************************** 函数学习: 1、创建/获取 int shmget(key_t key, size_t size, int shmflg); 参数一:键值 参数二:所创建共享内存的大小 参数三:如果键值不存在且本参数是IPC_CREAT,则会创建 返回值:成功:描述符 失败:-1 2、映射 void *shmat(int shmid, const void *shmaddr, int shmflg); 参数一: 共享内存id 参数二:要映射的地址,一般设置为NULL,让系统自动选用映射地址 参数三:标志 返回值:成功:地址 失败: -1 3、分离 int shmdt(const void *shmaddr); 并不是删除,分离后,key依旧存在 参数:要断掉的共享内存的地址 返回值:成功0 失败-1 4、控制 (1)删除:int shmctl(int shmid, int cmd, struct shmid_ds *buf); 参数一:共享内存标识符 参数二: 决定要执行的操作,例如IPC_RMID是删除 参数三:获取linux中描述共享内存的结构,基本不使用,一般为0 返回值:失败-1 成功0 综合实例: 两个进程: read 和 write write: 获取键盘输入的字符串并放入共享内存 read: 读取共享内存并打印 ************************************************************/ #include "mytype.h" /*********************************************************** write 进程执行流程: 1、创建共享内存 2、映射共享内存到应用程序 3、使用 4、脱离共享内存 ************************************************************/ int main() { bool running = true; char buf[BUF_SIZE]; SHMEM_USE_ST shm_ctl; SHMEM_AREA* shm_area; // 1.创建共享内存 shm_ctl.key = ftok("/home/kun", 1212); shm_ctl.shmid = shmget(shm_ctl.key, sizeof(SHMEM_AREA), IPC_CREAT); if(shm_ctl.shmid < 0) { DEBUG_ERROR("share memory creat or get failed . "); } // 2.映射共享内存地址到本应用程序中 shm_area = (SHMEM_AREA *)shmat(shm_ctl.shmid, NULL, 0); // 3.使用 while(running) { // 等待read进程读走数据 while(!shm_area->isnull) { DEBUG_INFO("wait read process ... "); sleep(1); } // 键盘输入 DEBUG_PRINTF("Please enter : "); fgets(buf, BUF_SIZE, stdin); strncpy(shm_area->data, buf, sizeof(buf)); shm_area->isnull = false; // 检测结束条件 if(strncmp(buf, "end", 3) == 0) { running = false; } } // 4.脱离共享内存 if(shmdt((const void *)shm_area) < 0) { DEBUG_ERROR("write process shmdt failed . "); } return 0; } /**************************************************************************************** * 文件名: read.c * 创建者: * 时 间: * 联 系: * 简 介: *****************************************************************************************/ #include "mytype.h" /*********************************************************** read 进程执行流程: 1、获取共享内存 2、映射 3、使用 4、脱离 5、删除 ************************************************************/ int main() { bool running = true; SHMEM_AREA* shm_area; SHMEM_USE_ST shm_use; // 1.获取共享内存 shm_use.key = ftok("/home/kun", 1212); if((shm_use.shmid=shmget(shm_use.key, sizeof(SHMEM_AREA), IPC_CREAT)) < 0) { DEBUG_ERROR("get share memory failed . "); exit(EXIT_FAILURE); } // 2.映射共享内存 shm_area = (SHMEM_AREA *)shmat(shm_use.shmid, NULL, 0); // 3.使用 shm_area->isnull = true; //因为先运行read进程,所以第一次读取共享内存的时候一定是空的 while(running) { // 等待有数据写入 while(shm_area->isnull == true) { // DEBUG_INFO("read process wait ... "); sleep(1); } // 检测结束标记 if(strncmp(shm_area->data, "end", 3) == 0) { running = false; break; } DEBUG_PRINTF("read data is : %s ", shm_area->data); shm_area->isnull = true; } // 4.脱离 if(shmdt((const void *)shm_area) < 0) { DEBUG_WARNING("read process shmdt failed . "); } // 5.删除共享内存 if( shmctl(shm_use.shmid, IPC_RMID, NULL) == 0 ) { DEBUG_INFO("delete share memory successful ! "); }else{ DEBUG_WARNING("remove share memory failed . "); } return 0; } /**************************************************************************************** * 文件名: mytype.h * 创建者: Kun * 时 间: 2018/0/12 * 联 系: 153471503@qq.com * 简 介: linux常用类型定义 *****************************************************************************************/ #ifndef _MYTYPE_H_ #define _MYTYPE_H_ //--------------------------< 预添加头文件包含 >----------------------// #define USE_TIME 0 #define USE_SIGNAL 0 #define USE_SHARE_MEMORY 1 #define USE_SEMAPHORE 0 #define USE_FILE_CTL 0 //-------------------------------< end ----------------------------// //---------------------------< includes >---------------------------// // c标准库头文件 #include #include #include // 信号使用相关头文件 #if USE_SIGNAL #include #endif // USE_SIGNAL // 信号量操作相关头文件 #if USE_SEMAPHORE #include #include #endif // USE_SEMAPHORE // 共享内存操作相关头文件 #if USE_SHARE_MEMORY #include #endif // USE_SHARE_MEMORY // 系统调用式文件编程头文件 #include // 该文件所定义的接口通常都是大量针对系统调用的封装, // 如 fork、pipe 以及各种 I/O 原语(read、write、close 等等)。 #include // linux系统中类型定义相关头文件 #include // 文件状态,是unix/linux系统定义文件状态所在的伪标准头文件。 #if USE_FILE_CTL #include #endif // USE_FILE_CTL #if USE_TIME // 时间编程相关头文件 #include #endif // USE_TIME //-------------------------< includes end >-------------------------// // bool类型定义 #ifndef bool typedef unsigned int bool; #endif enum { true = 1, false = !true }; // 常用无符号数据类型定义 typedef unsigned int uint; typedef unsigned char uchar; typedef unsigned short ushort; //----------------------< 调试信息输入相关宏定义 >----------------------// #define DEBUG_INFO(...) printf("Info: "); printf(__VA_ARGS__) #define DEBUG_ERROR(...) printf("Error: "); printf(__VA_ARGS__) #define DEBUG_WARNING(...) printf("Warning: "); printf(__VA_ARGS__) #define DEBUG_PRINTF(...) printf(__VA_ARGS__) //------------------------------------------------------------------// // 信号量使用封装结构 #if USE_SEMAPHORE typedef struct sem_use_st SEM_USE_ST; struct sem_use_st { int semid; key_t key; struct sembuf sops; }; #endif // USE_SEMAPHORE // 共享内存使用封装结构 #if USE_SHARE_MEMORY typedef struct shmem_use_st SHMEM_USE_ST; struct shmem_use_st { int shmid; key_t key; }; #define BUF_SIZE 1024*1 //共享内存大小 typedef struct shmem_area SHMEM_AREA; struct shmem_area { bool isnull; char data[BUF_SIZE]; }; #endif // USE_SHARE_MEMORY #endif // _TYPE_H_

【Makefile】

这里写图片描述

【运行结果】

引用块内容

end