Makefile模板和工程模板(消息队列和共享内存)的使用

一、 Makefile模板

#指定生成的文件名
OJB_OUT = test#指定每一个c文件对应的.o文件
OBJS = a.o b.o main.o#指定编译器
CC = gcc#指定需要的库
ULDFLAGS = ###########################################
#以下的内容不需要修改
###########################################
all:$(OJB_OUT)$(OJB_OUT):$(OBJS)$(CC) -o $@ $^ $(ULDFLAGS)dep_files := $(foreach f,$(OBJS),.$(f).d)
dep_files := $(wildcard $(dep_files))ifneq ($(dep_files),)include $(dep_files)
endif$(OBJS):%.o:%.c$(CC) -Wp,-MD,.$@.d -c $< -o $@clean:rm -rf .*.o.d *.o $(OJB_OUT)

二、 工程模板(消息队列和共享内存)

1. pub_define.h

/***********************************************************************************
Description:    类型重定义
***********************************************************************************/
#ifndef __PUB_DEFINE_H
#define __PUB_DEFINE_H#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>#define MAX_PROC_NAME_SZ    32#define MAX_PATH_LEN 256  //最大路径长度#ifdef BOOL
#undef BOOL
#endif#ifdef FALSE
#undef FALSE
#endif#ifdef TRUE
#undef TRUE
#endif#define BOOL    int
#define FALSE   (0)
#define TRUE    (!FALSE)#define KB 1024
#define MB (1024*KB)
#define GB (1024*MB)#define UNUSED(x) (void)x;  //仅仅为了消除警告用,可解决未定义变量#include <stdint.h>#define uint8  uint8_t
#define uint16 uint16_t
#define uint32 uint32_t#define int8  int8_t
#define int16 int16_t
#define int32 int32_t#define SLEEP_MS(ms) usleep(ms*1000)#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))#endif //__PUB_DEFINE_H

2. msg_queue_peer.h

/***********************************************************************************
Description:    点对点型消息队列组件
***********************************************************************************/#ifndef MSG_QUEUE_PEER_H
#define MSG_QUEUE_PEER_H#include "pub_define.h"
#include <sys/ipc.h>
#include <sys/msg.h>int msg_queue_send(const char *name, const void *msg, size_t msgsz, int msgflg);
int msg_queue_recv(const char *name, void *msg, size_t msgsz, long msgtyp, int msgflg);#endif  // MSG_QUEUE_PEER_H

3. shmem.h

/***********************************************************************************
Description:    提供共享内存组件
***********************************************************************************/#ifndef SHMEM_H
#define SHMEM_H#include "pub_define.h"
#include <sys/ipc.h>
#include <sys/shm.h>#define SHM_NAME_SZ    32struct shm_param
{int id;                       //共享内存IDsize_t size;void *addr;                   //共享内存地址char name[SHM_NAME_SZ+1];     //共享内存key标识
};int shm_init(struct shm_param *para, const char *name, size_t size);
void *shm_getaddr(struct shm_param *para);
void shm_write(const struct shm_param *para, void *data, size_t size);
int shm_del(const struct shm_param *para);#endif  // SHMEM_H

4. msg_queue_peer.c

/***********************************************************************************
Description:    点对点型消息队列组件
***********************************************************************************/#include <errno.h>
#include "msg_queue_peer.h"#define MSG_PATH "/tmp/ipc/msgqueue/peer/"#define MAGIC_ID 'j'/*** @brief msg_queue_send* @param name 发送给哪个消息队列* @param msg 消息数据,第一个字段必须是long类型的消息类型* @param msgsz 整个msg大小,不需要减去long--sizeof(*msg)* @param msgflg 同msgsnd* @return 同msgsnd*/
int msg_queue_send(const char *name, const void *msg, size_t msgsz, int msgflg)
{assert(NULL != name && strlen(name) > 0);assert(NULL != msg);key_t key;int ret;int msgid;char sys_cmd[256];char path[256];sprintf(path, "%s%s", MSG_PATH, name);//文件不存在创建if(access(path, F_OK) < 0){sprintf(sys_cmd, "%s %s", "touch", path);ret = system(sys_cmd);UNUSED(ret);}//创建keykey = ftok(path, MAGIC_ID);if(key < 0){perror("fail to ftok");return -1;}//创建消息队列msgid = msgget(key, IPC_CREAT|0666);if (msgid < 0){perror("fail to msgget");return -1;}return msgsnd(msgid, msg, msgsz - sizeof(long), msgflg);
}/*** @brief msg_queue_send* @param name 从哪个消息队列接收* @param msg 消息缓冲区,第一个字段必须是long类型的消息类型* @param msgsz 整个msg大小,不需要减去long--sizeof(*msg)* @param msgtyp 同msgrcv* @param msgflg 同msgrcv* @return 同msgrcv*/
int msg_queue_recv(const char *name, void *msg, size_t msgsz, long msgtyp, int msgflg)
{assert(NULL != name && strlen(name) > 0);assert(NULL != msg);key_t key;int ret;int msgid;char sys_cmd[256];char path[256];sprintf(path, "%s%s", MSG_PATH, name);//文件不存在创建if(access(path, F_OK) < 0){sprintf(sys_cmd, "%s %s", "touch", path);ret = system(sys_cmd);UNUSED(ret);}//创建keykey = ftok(path, MAGIC_ID);if(key < 0){perror("fail to ftok");return -1;}//创建消息队列msgid = msgget(key, IPC_CREAT|0666);if (msgid < 0){perror("fail to msgget");return -1;}return msgrcv(msgid, msg, msgsz - sizeof(long), msgtyp, msgflg);
}/*** @brief 判断某个类型的消息是否存在,但是不取出* @param name 指定消息队列名* @param msgtyp 消息类型* @return TRUE FALSE*/
BOOL msg_queue_msgexist(const char *name, long msgtyp)
{assert(NULL != name && strlen(name) > 0);key_t key;int ret;int msgid;char sys_cmd[256];char path[256];sprintf(path, "%s%s", MSG_PATH, name);//文件不存在创建if(access(path, F_OK) < 0){sprintf(sys_cmd, "%s %s", "touch", path);ret = system(sys_cmd);UNUSED(ret);}//创建keykey = ftok(path, MAGIC_ID);if(key < 0){perror("fail to ftok");return -1;}//创建消息队列msgid = msgget(key, IPC_CREAT|0666);if (msgid < 0){perror("fail to msgget");return -1;}if(msgrcv(msgid, NULL, 0, msgtyp, IPC_NOWAIT) < 0){if(errno == E2BIG){return TRUE;}}return FALSE;
}

5. shmem.c

/***********************************************************************************
Description:    提供共享内存组件
***********************************************************************************/#include "shmem.h"#define MAGIC_ID 'j'/*** @brief 初始化共享内存* @param para 参数结构体,传入即可* @param name 共享内存标识名称* @return 0 -1*/
int shm_init(struct shm_param *para, const char *name, size_t size)
{assert(NULL != para);assert(NULL != name && strlen(name) > 0);key_t key;int ret;int id;char sys_cmd[256];char path[256];sprintf(path, "/tmp/ipc/shmem/%s", name);sprintf(sys_cmd, "%s %s", "touch", path);ret = system(sys_cmd);UNUSED(ret);//创建keykey = ftok(path, MAGIC_ID);if(key < 0){perror("fail to ftok");printf("error :path = %s\n", path);return -1;}//创建共享内存id = shmget(key, size, IPC_CREAT|0666);if (id < 0){perror("fail to shmget");return -1;}para->id = id;para->size = size;strcpy(para->name, name);return 0;
}/*** @brief 获取共享内存地址* @param para* @return 失败返回NULL*/
void *shm_getaddr(struct shm_param *para)
{void *addr;addr = shmat(para->id, NULL, 0);if(addr == (void *)-1){para->addr = NULL;}else{para->addr = addr;}return para->addr;
}/*** @brief 写共享内存* @param para* @param data* @param size*/
void shm_write(const struct shm_param *para, void *data, size_t size)
{assert(size <= para->size);assert(NULL != data);memcpy(para->addr, data, size);
}/*** @brief 解除共享内存* @param para* @return*/
int shm_del(const struct shm_param *para)
{assert(NULL != para);int ret = shmdt(para->addr);if(ret < 0){perror("fail to shmdt");return -1;}ret = shmctl(para->id, IPC_RMID, NULL);if(ret < 0){perror("fail to shmctl");return -1;}return 0;
}

6. main.c

#include <stdio.h>int main(int argc, char *argv[])
{printf("project demo\n");return 0;
}

7. Makefile

#指定生成的文件名
OJB_OUT = test#指定每一个c文件对应的.o文件
OBJS = shmem.o msg_queue_peer.o main.o#指定编译器
CC = gcc#指定需要的库和路径
ULDFLAGS = ###########################################
#以下的内容不需要修改
###########################################
all:$(OJB_OUT)$(OJB_OUT):$(OBJS)$(CC) -o $@ $^ $(ULDFLAGS)dep_files := $(foreach f,$(OBJS),.$(f).d)
dep_files := $(wildcard $(dep_files))ifneq ($(dep_files),)include $(dep_files)
endif$(OBJS):%.o:%.c$(CC) -Wp,-MD,.$@.d -c $< -o $@clean:rm -rf .*.o.d *.o $(OJB_OUT)

三、工程模板中通信组件的使用

以下组件依赖临时目录,必须提前创建(tmp目录是内存型目录,如果重启了系统会消失,所以每次重启后注意重新创建下)

mkdir /tmp/ipc/shmem -p
mkdir /tmp/ipc/msgqueue/peer -p

1.  消息队列

源码阅读:

(1)发送程序:

#include "msg_queue_peer.h"struct msgbuf
{long mtype;char mdata[256];
};int main(int argc, char *argv[])
{struct msgbuf send_buf;//这个mtype可以不用,但是必须赋一个不小于0的数send_buf.mtype = 1;while (1){gets(send_buf.mdata, 256);if(msg_queue_send("topic", &send_buf, sizeof(send_buf), 0) < 0){printf("msg_queue_send error\n");return -1;}}return 0;
}

(2)接收程序:

#include "msg_queue_peer.h"struct msgbuf
{long mtype;char mdata[256];
};int main(int argc, char *argv[])
{struct msgbuf recv_buf;while (1){if(msg_queue_recv("topic", &recv_buf, sizeof(recv_buf), 0, 0) > 0){printf("recv from msga type = %ld\n", recv_buf.mtype);printf("recv from msga data = %s\n", recv_buf.mdata);}else{perror("recv error:");return -1;}}return 0;
}

2. 共享内存

(1)写入共享内存

#include "shmem.h"static struct shm_param para;struct student
{int num;char name[64];
};int main(int argc, char *argv[])
{int ret = -1;ret = shm_init(&para, "shm_test", 1024);if(ret < 0){return -1;}struct student *addr = shm_getaddr(&para);if(addr == NULL){return -1;}addr->num = 10;strcpy(addr->name, "zhangsan");return 0;
}

(2)读取共享内存

#include "shmem.h"static struct shm_param para;struct student
{int num;char name[64];
};int main(int argc, char *argv[])
{int ret = -1;ret = shm_init(&para, "shm_test", 1024);if(ret < 0){return -1;}struct student *addr = shm_getaddr(&para);if(addr == NULL){return -1;}printf("num = %d\n", addr->num);printf("num = %s\n", addr->name);shm_del(&para);return 0;
}

3. 共享内存中读写结构体数组的使用

  假设学生信息结构体定义如下:

struct student
{int num;char name[16];
}

定义a、b两个进程,a进程创建若干个(个数自己决定,是可变的)学生,填充任意的信息,通过共享内存将学生信息共享给b进程(包括学生个数)。b进程拿到信息后打印到终端。

提示:这里可巧妙的利用指针的操作,先申请足够大的共享内存,映射后然后通过不同类型的指针来操作和读取内容中的数据。模型图如下:

(1)共享内存写入结构体数组和大小

#include "shmem.h"static struct shm_param para;struct student
{int num;char name[64];
};static int *total;  //指向共享内存中数据节点总个数
static struct student *node_arr;  //指向共享内存中节点缓存数组头#define MAX_NODE 128  //最大支持学生数目
#define STD_NODE_LEN sizeof(struct student)
#define MAX_NODE_SIZE (MAX_NODE * STD_NODE_LEN)int main(int argc, char *argv[])
{int ret = -1;ret = shm_init(&para, "shm_test", MAX_NODE_SIZE);if(ret < 0){return -1;}void *node_p = shm_getaddr(&para);if(node_p == NULL){return -1;}memset(node_p, 0, MAX_NODE_SIZE);//前4个字节存储实际的学生数目total = (int *)node_p;//后面空间存储数据点node_arr = (struct student *)(node_p + sizeof(int));*total = 3;  //假设有3个人//第1个人赋值node_arr[0].num = 1;strcpy(node_arr[0].name, "zhangsan");//第2个人赋值node_arr[1].num = 2;strcpy(node_arr[1].name, "lisi");//第3个人赋值node_arr[2].num = 3;strcpy(node_arr[2].name, "wangwu");return 0;
}

 (2)共享内存读取结构体数组

#include "shmem.h"static struct shm_param para;struct student
{int num;char name[64];
};static int *total;  //指向共享内存中数据节点总个数
static struct student *node_arr;  //指向共享内存中节点缓存数组头#define MAX_NODE 128  //最大支持学生数目
#define STD_NODE_LEN sizeof(struct student)
#define MAX_NODE_SIZE (MAX_NODE * STD_NODE_LEN)int main(int argc, char *argv[])
{int ret = -1;ret = shm_init(&para, "shm_test", MAX_NODE_SIZE);if(ret < 0){return -1;}void *node_p = shm_getaddr(&para);if(node_p == NULL){return -1;}//前4个字节存储实际的学生数目total = (int *)node_p;//后面空间存储数据点node_arr = (struct student *)(node_p + sizeof(int));printf("num = %d\n", *total);int i;for(i=0; i<*total; i++){printf("num=%d, name=%s\n", \node_arr[i].num,\node_arr[i].name);}//这个接口只有在这块共享内存不用了才能删除,项目中如果一直使用,不要调用这个接口shm_del(&para);return 0;
}

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

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

相关文章

NASA和uAvionix在AAM测试场部署SkyLine C2指挥和控制服务

蒙大拿州比格福克和弗吉尼亚州汉普顿2023年07月28日——美国宇航局和uAvionix签署了一项太空法案协议&#xff0c;为城市环境中的无人机系统 (UAS)开发先进的超视距(BVLOS)指挥和控制(C2)技术。根据协议&#xff0c;NASA将与uAvionix合作&#xff0c;利用基于互联网的基础设施和…

(二)Spring WeFlux响应式编程第二种整合方案|道法术器

Spring WebFlux 响应式异步编程|道法术器(一) Spring WeFlux响应式编程整合另一种方案|道法术器(二) R2dbc操作mysql 注意下面红色部分与上一篇"Spring WebFlux 响应式异步编程|道法术器(一)" 不一样的依赖包 技术整合: <!--设置spring-boot依赖的版本 --> &l…

kafka部署

1.kafka安装部署 1.1 kafaka下载 https://archive.apache.org/dist/kafka/2.4.0/kafka_2.12-2.4.0.tgz Binary downloads是指预编译的软件包,可供直接下载和安装,无需手动编译。在计算机领域中,二进制下载通常指预构建的软件分发包,可以直接安装在系统上并使用 "2.…

麒麟-飞腾Kylin-V4桌面arm64系统静态编译QT

1.系统具体版本&#xff1a; 2. 因为此版本的源很老了&#xff0c;需要修改版本的源&#xff0c;才能正常更新各种软件&#xff0c;否则&#xff0c;你连麒麟商店都打不开。 sudo vi /etc/apt/sources.list 选择你系统对应版本的源地址&#xff1a; #4.0.2桌面版本: deb ht…

ModuleNotFoundError: No module named ‘_sqlite3‘

前言 遇到报错信息如下&#xff1a; ModuleNotFoundError: No module named _sqlite3解决方式 参考解决方式&#xff1a; https://blog.csdn.net/jaket5219999/article/details/53512071 find / -name _sqlite*.socp /usr/lib64/python3.6/lib-dynload/_sqlite3.cpython-36…

uniapp 路由跳转方式

export function goBack(index, url) {if (index 1) { // 关闭当前页&#xff0c;返回上一页面或多级页面。uni.navigateBack({delta: url,animationType: pop-out,animationDuration: 300});} else if (index 2) { // 保留当前页&#xff0c;跳转到非tabbar页面&#xff0c;…

vue拖拽改变宽度

1.封装组件ResizeBox.vue <template><div ref"resize" class"resize"><div ref"resizeHandle" class"handle-resize" /><slot /></div> </template> <script> export default {name: Resi…

【Docker】使用docker-maven-plugin插件构建发布推镜像到私有仓库

文章目录 1. 用docker-maven-plugin插件推送项目到私服docker1.1. 构建镜像 v1.01.2. 构建镜像 v2.01.3. 推送到镜像仓库 2. 拉取私服docker镜像运行3. 参考资料 本文描述了在Spring Boot项目中通过docker-maven-plugin插件把项目推送到私有docker仓库中&#xff0c;随后拉取仓…

pgsql 查看某个表建立了那些索引sql

执行以下sql&#xff1a; SELECTns.nspname as schema_name,tab.relname as table_name,cls.relname as index_name,am.amname as index_type,idx.indisprimary as is_primary,idx.indisunique as is_unique FROMpg_index idx INNER JOIN pg_class cls ON cls.oididx.indexrel…

小程序相较于APP,广告变现有哪些优势?

对于开发者而言&#xff0c;微信小程序开发门槛相对较低&#xff0c;难度不及APP&#xff0c;能够满足简单的基础应用&#xff0c;适合生活服务类线下商铺以及非刚需低频应用的转换。 和早期相比&#xff0c;今天小程序在产品功能、UI设计、交互体验等方面&#xff0c;越来越精…

【深度学习】MAT: Mask-Aware Transformer for Large Hole Image Inpainting

论文&#xff1a;https://arxiv.org/abs/2203.15270 代码&#xff1a;https://github.com/fenglinglwb/MAT 文章目录 AbstractIntroductionRelated WorkMethod总体架构卷积头Transformer主体Adjusted Transformer Block Multi-Head Contextual Attention Style Manipulation Mo…

在排序数组中查找元素的第一个和最后一个位置——力扣34

文章目录 题目描述法一 二分查找 题目描述 法一 二分查找 int bsearch_1(int l, int r) {while (l < r){int mid (l r)/2;if (check(mid)) r mid;else l mid 1;}return l; }int bsearch_2(int l, int r) {while (l < r){int mid ( l r 1 ) /2;if (check(mid)) l …

Istio 安全 mTLS认证 PeerAuthentication

这里定义了访问www.ck8s.com可以使用http也可以使用https访问&#xff0c;两种方式都可以访问。 那么是否可以强制使用mtls方式去访问&#xff1f; mTLS认证 PeerAuthentication PeerAuthentication的主要作用是别人在和网格里的pod进行通信的时候&#xff0c;是否要求mTLS mTL…

链表OJ:环形链表

Lei宝啊&#xff1a;个人主页 愿所有美好与我们不期而遇 题目描述 &#xff1a; 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 接口&#xff1a; bool hasCycle(struct ListNode *head) 示例1&#xff1a; 示例2&#xff1a; 返回值&#xff1a; true或…

十分钟配置好Neovim go开发环境(其他语言一样)

文章目录 前言仓库地址用法快捷键问题反馈 前言 这篇文章的目的是为了分享下我自己的Neovim配置。 本人是Golang程序员&#xff0c;最开始使用的IDE是JetBrains Goland。有一说一这个ide适配度很高&#xff0c;认识的很多人都使用这个。但是它也有几个对我来说的缺点&#xf…

认识C语言

目录 1.C语言的发展历史 2.C语言的特点 3.C语言的应用领域 1.C语言的发展历史 C语言的发展历史可以追溯到20世纪60年代。在那个时候&#xff0c;计算机科学领域存在着多种编程语言&#xff0c;但它们在功能、效率和可移植性等方面存在一些限制。 C语言的起源可以追溯到贝尔实…

在矩池云使用Llama2-7B的具体方法

今天给大家分享如何在矩池云服务器使用 Llama2-7b模型。 硬件要求 矩池云已经配置好了 Llama 2 Web UI 环境&#xff0c;显存需要大于 8G&#xff0c;可以选择 A4000、P100、3090 以及更高配置的等显卡。 租用机器 在矩池云主机市场&#xff1a;https://matpool.com/host-m…

快应用编译前如何统一替换字符串

假设你有一个需求&#xff0c;要把代码里的ad-button替换为div&#xff0c;因为是mi看ad-button不爽。 这还不简单么&#xff0c;webpack有那么多成熟的plugins和loaders&#xff0c;本身我对webpack也只是略知一二&#xff0c;随便一搜网上的解决方案&#xff0c; string-re…

发点实用的快捷键(mac

切换输入法&#xff1a;ctrlspace /ctrloptionspace&#xff08;更快捷 切换网页&#xff1a; shifttab 切换应用界面&#xff1a;alttab 关闭页面&#xff1a;altw 搜索&#xff1a;altspace 展示mac隐藏文件&#xff1a; Commangshift . (点) 以下是一些浏览器快捷键&am…

Windows磁盘清理

针对开发同学&#xff0c;磁盘不够用时&#xff0c;常见的需要清理的内容&#xff1a; 1、虚拟机镜像、Docker镜像等。 通常占用比较大的存储&#xff0c;一个实例从几个G到几十个G。 2、Maven本地仓库。 如果公司有私服&#xff0c;可以全部删掉重新依赖&#xff0c;否则不…