linux c共享内存和信号量

编译环境:Ubuntu16.04 64位
交叉编译工具:arm-hisiv500-linux-gcc

文章目录

  • 1. 项目背景
  • 2. 涉及的函数
  • 3. 头文件JShm.h
  • 4. 类的实现
  • 5. sample代码

1. 项目背景

最近项目中需要用到共享内存的交互,自己造个轮子吧。

2. 涉及的函数

详细描述可以百度或ubuntu下查询man手册。
共享内存相关:
int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

信号量相关:
int semget(key_t key,int nsems,int semflg);
int semctl(int semid,int semnum,int cmd, /union semun arg/);
semctl是可变参数长度的函数
int semop(int semid, struct sembuf *sops, size_t nsops);

3. 头文件JShm.h


#include <errno.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>#ifndef __J_SHM__
#define __J_SHM__#ifdef __cplusplus
extern "C" {
#endif
class JShm {
public:JShm(int key, unsigned int size);~JShm();int Write(unsigned char *buf, unsigned int len);int Read(unsigned char *buf, unsigned int len);private:int Init();int UnInit();int SemP();int SemV();static unsigned int IsPower2(unsigned int size);	static unsigned int To2N(unsigned int size);
private:key_t m_shmKey;unsigned int m_size;		// 共享内存大小unsigned char *m_buffer; 	// 共享内存地址int m_shmID;int m_semID;
};#ifdef __cplusplus
}
#endif
#endif // __J_SHM__

4. 类的实现

#include "JShm.h"union SemUnion {int val;struct semid_ds *buf;
};struct ShmHead {unsigned int len;  		// 数据长度unsigned int refresh; 	// 数据是否被覆盖unsigned int res[2];
};unsigned int JShm::IsPower2(unsigned int size)
{if (size == 0)return 0;return ((size & (size - 1)) == 0);
}unsigned int JShm::To2N(unsigned int size)
{unsigned int i = 1;unsigned int tmp = size;while (size >>= 1){i <<= 1;}return (i < tmp) ? i << 1 : i;
}// 构造时,请务必保证双方的key和size相同
JShm::JShm(int key, unsigned int size)
{m_shmKey = key;unsigned int nSize = IsPower2(size) ? size : To2N(size);;m_size = nSize + sizeof(ShmHead);m_buffer = NULL;m_shmID = -1;m_semID = -1;Init();
}JShm::~JShm()
{UnInit();
}int JShm::Init()
{m_shmID = shmget(m_shmKey, m_size, IPC_CREAT | IPC_EXCL | 0666);if (m_shmID < 0){if (errno != EEXIST){return -1;}m_shmID = shmget(m_shmKey, m_size, IPC_CREAT | 0666);if (m_shmID < 0){m_shmID = shmget(m_shmKey, 0, 0666);if (m_shmID < 0){return -1;}if (shmctl(m_shmID, IPC_RMID, NULL)!= 0){return -1;}m_shmID = shmget(m_shmKey, m_size, IPC_CREAT | IPC_EXCL | 0666);if (m_shmID < 0){return -1;}}}m_buffer = (unsigned char *)shmat(m_shmID, NULL, 0);if (m_buffer == (unsigned char *)-1){return -1;}memset(m_buffer, 0, m_size);m_semID = semget(m_shmKey, 1, 0666 | IPC_CREAT);if (m_semID < 0){return -1;}union SemUnion semUnion;semUnion.val = 1;semctl(m_semID, 0, SETVAL, semUnion);return 0;
}int JShm::UnInit()
{shmdt(m_buffer);m_buffer = NULL;shmctl(m_shmID, IPC_RMID, NULL);m_shmID = -1;semctl(m_semID, 0, IPC_RMID);m_semID = -1;return 0;
}int JShm::SemP()
{// 申请信号,信号量-1sembuf semP;semP.sem_num = 0;semP.sem_op = -1;semP.sem_flg = SEM_UNDO;semop(m_semID, &semP, 1);return 0;
}int JShm::SemV()
{// 释放信号,信号量+1sembuf semV;semV.sem_num = 0;semV.sem_op = 1;semV.sem_flg = SEM_UNDO;semop(m_semID, &semV, 1);return 0;
}// buf:要写入的数据
// len:要写入的数据的长度
// 返回值:>=0表示成功,0成功,1覆盖旧数据,-1表示失败
int JShm::Write(unsigned char *buf, unsigned int len)
{if (m_buffer == NULL || len > m_size)return -1;int ret = 0;SemP();ShmHead *head = (ShmHead *)m_buffer;head->len = len;memcpy(m_buffer + sizeof(ShmHead), buf, len);if (head->refresh)ret = 1;head->refresh = 1;SemV();return ret;
}// buf:读数据的缓冲区
// len:缓冲区的长度
// 返回值:实际读取到的长度,0表示失败
int JShm::Read(unsigned char *buf, unsigned int len)
{if (m_buffer == NULL)return 0;int ret = 0;SemP();ShmHead *head = (ShmHead *)m_buffer;if (len < head->len) {SemV();return 0;}memcpy(buf, m_buffer + sizeof(ShmHead), head->len);head->refresh = 0;ret = head->len;SemV();return ret;
}

5. sample代码

#include <stdio.h>#define SHM_KEY   101
#define SHM_SIZE  1024
int main(int argc, char* argv[])
{if (argc < 2){return -1;}if (argv[1][0] == 'w'){JShm *ShmWrite = new JShm(SHM_KEY, SHM_SIZE);while (true){char writeBuf[128] = {0};fgets(writeBuf, sizeof(writeBuf), stdin);if (writeBuf[0] == 'q'){delete ShmWrite;return 0;}printf("write data:%s\n", writeBuf);ShmWrite->Write((unsigned char *)writeBuf, strlen(writeBuf));}} else if (argv[1][0] == 'r') {JShm *ShmRead = new JShm(SHM_KEY ,SHM_SIZE);while (true) {char writeBuf[128] = {0};fgets(writeBuf, sizeof(writeBuf), stdin);if (writeBuf[0] == 'q'){delete ShmRead;return 0;}unsigned char readBuf[256] = { 0 };int ret = ShmRead->Read(readBuf, 255);printf("read %d data:%s\n", ret, readBuf);}}return 0;
}

编译完成之后,ubuntu下分别执行./a.out w和./a.out r测试。

以上。
转载请注明出处,如有错漏之处,敬请指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/804345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux进阶之旅:深入探索Linux的高级功能

文章目录 Linux进阶之旅:深入探索Linux的高级功能1. Shell脚本编程2. 进程管理3. 网络管理4. 文本处理5. 系统监控6. 总结 Linux进阶之旅:深入探索Linux的高级功能 在上一篇博客中,我们对Linux操作系统进行了入门级的介绍,包括Linux的特点、发行版、安装方法以及基本使用。接下…

python——输入/输出

输出 关键字 print()注意&#xff1a;print() 默认自带一个换行符\n 格式化输出 格式化符号 符号作用%s转换字符串%d有符号的十进制整数%f浮点数%c字符%u无符号的十进制整数%o八进制整数%x十六进制整数&#xff0c;小写ox%X十六进制整数&#xff0c;大写OX%e科学计数法&…

Proxmox VE qm 方式一键创建Windows虚拟机

前言 实现qm 方式一键创建Windows虚拟机&#xff0c;提高效率。 qm 一键创建Windows虚拟机 以下实现在线下载镜像&#xff0c;创建虚拟机&#xff0c;安装系统需要自己手动安装哦&#xff0c;如果想实现全自动安装系统&#xff0c;建议部署自己的内网pxe server 系统参考各参…

(一)ffmpeg 入门基础知识

一、ffmpeg FFmpeg是一套强大的开源音视频处理工具&#xff0c;能够录制、转换以及流化音视频内容。 FFmpeg是开源的&#xff0c;这意味着它的源代码是公开的&#xff0c;允许任何人使用、修改和分发。它提供了录制、转换以及流化音视频的完整解决方案&#xff0c;支持多种格…

【C语言】整数和浮点数在内存中的存储

点这里是个人主页~ 这次的内容是比较底层的奥&#xff0c;对于理解编程很重要~ 整数浮点数在内存中的存储 一、 整数在内存中的存储二、大小端字节序和字节序判断大小端的概念一道简单关于大小端排序的百度面试题 三、简单理解数据类型存储范围例一例二例三例四例五例六 四、 …

STM32F4 IAP跳转APP问题及STM32基于Ymodem协议IAP升级笔记

STM32F4 IAP 跳转 APP问题 ST官网IAP例程Chapter1 STM32F4 IAP 跳转 APP问题1. 概念2. 程序2.1 Bootloader 程序 问题现象2.2. APP程序 3. 代码4. 其他问题 Chapter2 STM32-IAP基本原理及应用 | ICP、IAP程序下载流程 | 程序执行流程 | 配置IAP到STM32F4xxxChapter3 STM32基于Y…

未来工厂大脑:图扑组态软件在智能制造中的应用

组态软件&#xff1a;一般英文简称有三种分别为 HMI/MMI/SCADA&#xff0c;中文翻译为&#xff1a;人机界面/监视控制和数据采集软件。 运行于 PC 平台的一个通用工具软件&#xff0c;涉及各行各业&#xff0c;其主要功能是对生产现场的运行设备进行监控并就危险情况进行报警&…

【学习】使用VScode连接服务器。

step1: 安装 Remote - ssh 扩展 step2&#xff1a; 进入步骤2中&#xff0c;进行文件配置。 step3&#xff1a; 点击箭头进行连接。 step4&#xff1a; 输入密码即可。选择 platform时候&#xff0c;选择使用 Linux&#xff0c;而不是windows。

FreeRTOS创建第一个程序

使用freeRTOS创建任务时使用如下函数 函数的参数 创建一个FreeRTOS任务点亮led灯实现led灯500毫秒翻转一次 具体的代码实现 #include "stm32f10x.h" // Device header #include "Delay.h" #include "freeRTOS.h" #include &quo…

PMP持证者在面试项目经理时有加持吗?

对PMP认证获取后是否在面试中加持很多人是没有体验过的&#xff0c;因为大部分人考取PMP认证的原因是因为公司的要求&#xff0c;没有这个证书可能面临被“优化”的风险。理论上来说一样的道理&#xff0c;PMP认证既然能够保住工作岗位&#xff0c;那么在面试中一定会有相应的作…

利用AI开源引擎平台:构建文本、图片及视频内容审核系统|可本地部署

网络空间的信息量呈现出爆炸式增长。在这个信息多元化的时代&#xff0c;内容审核系统成为了维护网络秩序、保护用户免受有害信息侵害的重要工具。本文将探讨内容审核系统的核心优势、技术实现以及在不同场景下的应用。 开源项目介绍(可本地部署&#xff0c;支持国产化) 思通数…

【RK平台 dumpsys info使用】

RK平台 dumpsys info使用 问题描述解决方法郑重声明:本人原创博文,都是实战,均经过实际项目验证出货的 转载请标明出处:攻城狮2015 Platform: Rockchip OS:Android 7.1.2 Kernel: 3.10 问题描述 在看问题的时候,经常需要查看内存情况,等各项指标 解决方法 1.常用的dumpsys …

Vue2 响应式原理

Vue 的响应式原理 Vue 的响应式原理基于"数据劫持"和"依赖收集"的概念。当我们将一个普通的 JavaScript 对象传递给 Vue 实例的 data 选项时&#xff0c;Vue 将遍历此对象的所有属性&#xff0c;并使用 Object.defineProperty()来对每个属性进行 getter 和…

Redis ttl与key过期策略

TTL ttl --- time to line 网络原理的IP协议当中&#xff0c;IP协议报头中&#xff0c;就有一个字段&#xff0c;TTL IP中的TTL不是用时间衡量过期的&#xff0c;而是用次数 功能&#xff1a;查看当前的key的过期时间还剩多少 语法&#xff1a; ttl key 时间复杂度&#xf…

12.C++常用的算法_遍历算法

文章目录 遍历算法1. for_each()代码工程运行结果 2. transform()代码工程运行结果 3. find()代码工程运行结果 遍历算法 1. for_each() 有两种方式&#xff1a; 1.普通函数 2.仿函数 代码工程 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<vect…

layui复选框勾选取消勾选事件监听

监听事件放置位置&#xff1a; form.on(checkbox(equipInputClick), function(data){var a data.elem.checked;var val data.value;if(a true){}else{}});html部分 <input lay-filter"equipInputClick" type"checkbox" lay-skin"primary&quo…

前端做了快两年了,盘点一下我的前端技术栈

前言 前言很简单&#xff0c;年终了&#xff0c;自己写了快两年前端&#xff08;虽然刚毕业&#xff09;&#xff0c;但是大致总结一下哈哈哈哈 我觉得这个话题蛮有意思的&#xff0c;可以看看大家的技术广度&#xff0c;可以进行分享和学习以及讨论 所以这里说一下我对我的…

# ABAP SQL 字符串处理

经常我都要在ABAP的sql语句中对字符串进行处理&#xff0c;现在就总结一下可以用到的方法 文章目录 字符串处理拼接字段运行结果 填充字符串运行结果 截取字符串 SUBSTRING运行结果 CAST转换类型程序运行结果 字符串处理 在SQL语句中&#xff0c;有时候会有需要拼接字段或者是…

车载平板电脑丨车载终端丨浅聊叉车仓储出入库管理解决方案

众所周知&#xff0c;叉车是制造业自动化升级的核心设备。 十三五期间&#xff0c;提出中国制造 2025 战略&#xff0c;其核心内容就是要用机器代替人工&#xff0c;提升生产效率&#xff0c;降低对劳动力的依赖性。而叉车作为起重、搬运等普通劳动力替代的核心设备&#xff0…

Spring中基于事件监听驱动 和 线程池的异步任务

文章目录 事件监听驱动 与 异步事件源ApplicationContextAware接口 发布事件事件实体监听事件实现异步注入綫程池 事件驱动机制&#xff0c;与MQ消息队列比较 事件监听驱动 与 异步 事件监听驱动优点&#xff1a;解耦&#xff0c;将 事件和业务进行解耦&#xff0c;通过Asyc注解…