ipc-test.bk and mmap is also similar.

1.config tab-4

vi /etc/virc或者

1.配置文件中如果要添加注释,不能用#,要使用”

2.u命令回退上次的操作

3.复制不带行号,在/etc/virc的末尾添加se mouse+=a

" add tab spaceset ts=4 "只设置这个就能把tab缩进为4,加上下面的tab直接被替换成4个空格,不是tab了,make出错"set softtabstop=4
"set shiftwidth=4
"set expandtab
"set autoindent" 显示行号,但是也会复制到行号,直接注释
"set nu

2.tree and makefile 

1.tree ipc/
ipc/
├── clean.sh
├── client
│   ├── client.c
│   └── client.h
├── include
│   └── global_api.h
├── ipc
├── main
│   └── main.c
├── makefile
└── server├── server.c└── server.h4 directories, 9 files2.cat makefile 
#gcc ./main/main.c ./server/server.c ./client/client.c -o ipc 
#只写这一行应该写在shell里而不是makefile
all: ipcipc: main/main.c server/server.c client/client.c  #加不加./都一样gcc -o ipc main/main.c server/server.c client/client.c # -o 在哪里都一样clean:rm -rf ipc3.cat clean.sh
make clean

3.注意事项:shm族函数并没有信号的通知机制,需要我们继续使用sem族函数 

 增加通知机制

server.c

cat server/server.c 
#include "../include/global_api.h"void server_init(){/*key_t key = ftok(".", 1); //使用绝对路径比较合适if(key < 0){printf("\nftok err.\n");}*/int shmid = shmget(IPC_KEY, sizeof(int), IPC_CREAT | 0664);//0666);if (shmid == -1) {  perror("shmget failed");  exit(1);  }char* shared_mem = (char*)shmat(shmid, NULL, 0);if(shared_mem == (void*)-1){perror("shmat failed");}struct sembuf op; int semid = semget(IPC_KEY, 1, IPC_CREAT | 0664);/*union semun arg;  //gcc 可能不支持,先注释掉arg.val = 0;  if (semctl(semid, 0, SETVAL, arg) == -1) {  perror("semctl SETVAL");  exit(1);  }*/ while(1){sleep(1);op.sem_num = 0;  // 信号量在信号量集中的索引op.sem_op = -1;   //阻塞等待通知的到来op.sem_flg = 0;  // 表示这是一次常规的操作if (semop(semid, &op, 1) == -1) {perror("semop");exit(1);}printf("i got it, shard_mem:[%s]\n", shared_mem);//[%c]\n", shared_mem);}	
}

client.c

cat client/client.c
#include "../include/global_api.h"void client_init(){int shmid = shmget(IPC_KEY, sizeof(int), IPC_CREAT);// | 0666);	if (shmid == -1) {  perror("shmget failed");  exit(1);  }char* shared_mem = (char*)shmat(shmid, NULL, 0);if(shared_mem == (void*)-1){perror("shmat failed");}struct sembuf op;  // 获取信号量集  int semid = semget(IPC_KEY, 1, 0);  if (semid == -1) {  perror("semget");  exit(1);  }  *shared_mem = 'a' - 1;  	while(1){sleep(1);*shared_mem += 1;op.sem_num = 0;  // 信号量在信号量集中的索引op.sem_op = 1;  // 通知op.sem_flg = 0;  //表示这是一次常规的操作if (semop(semid, &op, 1) == -1) {perror("semop");exit(1);}printf("\nclient modify the char.\n");}
}

 

 4.how to make the shared_mem to complete IPC(没有增加通知,只需要把上面3的code替换下来即可)

main.c

cat main/main.c 
#include "../include/global_api.h"int main(){pid_t server_pid = fork();if(server_pid < 0){printf("\nfork err\n");}else if(server_pid == 0){printf("\nfork server success.\n");server_init();}pid_t client_pid = fork();if(client_pid < 0){printf("\nfork err\n");}else if(client_pid == 0){printf("\nfork client success.\n");client_init();}else{int state;waitpid(server_pid, &state, 0);waitpid(client_pid, &state, 0);}return 0;
}

waitpid(server_pid, &state, 0); && waitpid(client_pid, &state, 0);是必须的,不然main进程直接返回了

server.c:server不用ftok生成唯一的key,直接在global_api.h里大家使用相同的IPC_KEY即可,shmget的第二个参数是共享内存的大小:

或者用一个更好的方法生成KEY:

    // 使用ftok生成一个唯一的键  key = ftok("/tmp", 'R');  if (key == (key_t)-1) {  perror("ftok");  exit(1);  }  
cat server/server.c 
#include "../include/global_api.h"void server_init(){/*key_t key = ftok(".", 1);if(key < 0){printf("\nftok err.\n");}*/int shmid = shmget(IPC_KEY, sizeof(int), IPC_CREAT | 0664);//0666)i;if (shmid == -1) {  perror("shmget failed");  exit(1);  }char* shared_mem = (char*)shmat(shmid, NULL, 0);if(shared_mem == (void*)-1){perror("shmat failed");}while(1){sleep(1);printf("shard_mem:[%s]\n", shared_mem);//[%c]\n", shared_mem);}	
}

server.h

cat server/server.h
void server_init();

client.c:client不用0664,因为server已经创建了共享空间的空间号,我们只需要加入即可

cat client/client.c
#include "../include/global_api.h"void client_init(){int shmid = shmget(IPC_KEY, sizeof(int), IPC_CREAT);// | 0666);	if (shmid == -1) {  perror("shmget failed");  exit(1);  }char* shared_mem = (char*)shmat(shmid, NULL, 0);if(shared_mem == (void*)-1){perror("shmat failed");}	shared_mem[0] = 'a'; //or *shared_mem = 'a';while(1){sleep(1);*shared_mem += 1;printf("\nclient modify the char\n");}
}

client.h

cat client/client.h
void client_init();

golbal_api.h

cat include/global_api.h 
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/wait.h>#include "../client/client.h"
#include "../server/server.h"#define IPC_KEY 1234

5.other code

dd if=/dev/zero of=/tmp/shared_memory bs=1M count=1这条命令在Linux或Unix系统中用于通过dd(data duplicator)工具创建一个特定大小的文件。具体来说:if=/dev/zero:指定输入文件为/dev/zero,这是一个特殊的设备文件,它提供无限的零字节(\0)。
of=/tmp/shared_memory:指定输出文件为/tmp/shared_memory。这意味着从输入文件(/dev/zero)读取的数据将被写入到这个文件中。
bs=1M:设置块大小为1兆字节(1MB)。这意味着每次从输入文件读取和写入输出文件的数据块大小是1MB。
count=1:指定从输入文件读取并写入输出文件的数据块数量为1。
综合起来,这条命令将创建一个大小为1MB的文件/tmp/shared_memory,文件内容全部为零字节。这样的文件常用于需要预定大小空白文件的场合,例如作为共享内存区域的占位符。进程A:
#include <stdio.h>  
#include <stdlib.h>  
#include <fcntl.h>  
#include <sys/mman.h>  
#include <unistd.h>  int main() {  int *flag_ptr;  int fd = open("/tmp/shared_memory", O_RDWR | O_CREAT, 0666);  if (fd == -1) {  perror("open");  exit(1);  }  // 将文件大小设置为足够大的值以容纳我们的int  if (ftruncate(fd, sizeof(int)) == -1) {  perror("ftruncate");  exit(1);  }  // 映射文件到内存中  flag_ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  if (flag_ptr == MAP_FAILED) {  perror("mmap");  exit(1);  }  // 写入flag  *flag_ptr = 1;  // 等待其他进程或进行其他操作...  // 清理  munmap(flag_ptr, sizeof(int));  close(fd);  return 0;  
}进程B:
#include <stdio.h>  
#include <stdlib.h>  
#include <fcntl.h>  
#include <sys/mman.h>  
#include <unistd.h>  int main() {  int *flag_ptr;  int fd = open("/tmp/shared_memory", O_RDWR);  if (fd == -1) {  perror("open");  exit(1);  }  // 映射文件到内存中  flag_ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  if (flag_ptr == MAP_FAILED) {  perror("mmap");  exit(1);  }  // 读取flag  int flag = *flag_ptr;  printf("Read flag: %d\n", flag);  // ... 进行其他操作 ...  // 清理  munmap(flag_ptr, sizeof(int));  close(fd);  return 0;  
}

匿名mmap:其实就是加了标志位,即MAP_SHAREDMAP_ANONYMOUS(或MAP_ANON),并且把使用的fd直接变成-1

#include <sys/mman.h>  
#include <unistd.h>  
#include <stdio.h>  int main() {  // 映射区域的大小,例如4个字节  size_t size = 4;  // 创建匿名映射区域  int *shared_memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);  if (shared_memory == MAP_FAILED) {  perror("mmap failed");  return 1;  }  // ... 后续代码 ...  
}

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

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

相关文章

Ubuntu24.04基本配置

目录 0. 前言1. 连接网络2. 更新源3. 安装并配置vim4. 设置用户sudo免密5. 同步双系统时间6. 设置终端颜色主题7. 设置中文输入法8. 调整Dock位置等9. 设置Grub10. 其它美化设置10.1 夜灯10.2 壁纸10.3 终端加强gnome-tweaks10.4 字体 11. 常用工具11.1 邮箱配置11.2 翻译工具1…

如何微调 Llama 3 进行序列分类?

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

图像滤波算法 python

1. 平均滤波 (Mean Filtering) 平均滤波是一种简单的线性滤波方法&#xff0c;通过取邻域内像素的平均值来平滑图像&#xff0c;从而去除噪声。 import cv2 import numpy as np# 读取图像 image cv2.imread(image.jpg)# 应用平均滤波 mean_filtered cv2.blur(image, (5, 5)…

极域卸载不干净导致无法重新安装问题:独家解决方案

文章目录 一、问题二、解决1.网上常规方法2.本贴特殊之处 三、致谢 一、问题 极域卸载不干净&#xff0c;导致无法重新安装。 二、解决 1.网上常规方法 1.regedit命令注册表删除 topdomain、mythware、{5FB4EEDF-6A79-45C3-B049-EF327CA03FCD} 2.删除极域对应tmp文件 网上…

迫在眉睫的革命:通用人工智能(AGI)与超级智能的竞赛

技术领域正处于一场将重新定义人类能力和理解边界的革命边缘。随着我们站在这一新时代的十字路口,开发通用人工智能(AGI)及其随后向超级智能的飞跃,不仅仅是一项科学努力,而是我们历史上的一个关键时刻。在这篇博客文章中,我们将深入探讨Leopold Aschenbrenner的文件《态…

Go微服务: 分布式之通过可靠消息实现最终一致性

通过可靠消息实现最终一致性 可靠消息&#xff0c;就是靠普消息&#xff0c;还是基于之前的这个案例 比如这个订单服务&#xff0c;无论你是先发送消息&#xff0c;还是先新建订单&#xff0c;它其实都是发送的不可靠消息就是说如果这个消息&#xff0c;像mysql事务那样&#…

德克萨斯大学奥斯汀分校自然语言处理硕士课程汉化版(第七周) - 结构化预测

结构化预测 0. 写在大模型前面的话1. 词法分析 1.1. 分词1.2. 词性标注 2.2. 句法分析 2.3. 成分句法分析2.3. 依存句法分析 3. 序列标注 3.1. 使用分类器进行标注 4. 语义分析 0. 写在大模型前面的话 在介绍大语言模型之前&#xff0c;先把自然语言处理中遗漏的结构化预测补…

【机器学习】机器学习与医疗健康在智能诊疗中的融合应用与性能优化新探索

文章目录 引言机器学习与医疗健康的基本概念机器学习概述监督学习无监督学习强化学习 医疗健康概述疾病预测诊断辅助个性化治疗方案制定 机器学习与医疗健康的融合应用实时健康监测数据预处理特征工程 疾病预测与优化模型训练模型评估 诊断辅助与优化深度学习应用 个性化治疗方…

如何使用 Magisk 获取 Google Pixel 4 或 Pixel 4 XL 的 Root 权限

How to root the Google Pixel 4 or Pixel 4 XL with Magisk How to root the Google Pixel 4 or Pixel 4 XL with Magisk 给国内新用户的 Google Pixel 使用指南 - 少数派 12.0.0 (SP1A.211105.002, Nov 2021) https://developers.google.com/android/images#flame 小米…

接口自动化Requests+Pytest基础实现

目录 1. 数据库以及数据库操作1.1 概念1.2 分类1.3 作用 2 python操作数据库的相关实现2.1 背景2.2 相关实现 3. pymysql基础3.1 整个流程3.2 案例3.3 Pymysql工具类封装 4 事务4.1 案例4.2 事务概念4.3 事务特征 5. requests库5.1 概念5.2 角色定位5.3 安装5.4 校验5.5 reques…

C语言学习笔记 库文件

文章目录 概述生成静态库及应用生成动态库及应用 概述 在C语言中&#xff0c;库分为静态库(.a)和动态库(.dll或.so)。 调用静态库时&#xff0c;编译器会把库文件编译到可执行文件(.exe)里&#xff1b; 调用动态库时&#xff0c;编译器不会把库文件编译到可执行文件(.exe)里&a…

“中新美”三重身份,能帮SHEIN解决上市问题吗?

一家公司的海外上市之路能有多复杂&#xff1f;辗转多地的SHEIN&#xff0c;可能是当前最有话语权回答这个问题的公司。最近&#xff0c;它又有了新消息。 在上市信息多次更改后&#xff0c;伦敦正在成为SHEIN最有可能的“着陆”点。巴伦周刊援引英国天空新闻报道称&#xff0…

Python01 -分解整包数据到各个变量操作和生成器

Python 的星号表达式可以用来解决这个问题。比如&#xff0c;你在学习一门课程&#xff0c;在学期末的时候&#xff0c;你想统计下家庭作业的平均成绩&#xff0c;但是排除掉第一个和最后一个分数。如果只有四个分数&#xff0c;你可能就直接去简单的手动赋值&#xff0c;但如果…

5、搭建前端项目

5.1 使用vite vue搭建 win r 打开终端 切换到你想要搭建的盘 npm init vitelatest跟着以下步骤取名即可 cd fullStackBlognpm installnpm run dev默认在 http://localhost:5173/ 下启动了 5.2 用vscode打开项目并安装需要的插件 1、删除多余的 HelloWorld.vue 文件 2、安装…

【Vue3】理解toRef() 和 toRefs()

历史小剧场 知道可能面对的困难和痛苦&#xff0c;在死亡的恐惧中不断挣扎&#xff0c;却仍然能战胜自己&#xff0c;选择这条道路&#xff0c;这才是真正的勇气。----《明朝那些事儿》 前言 toRef 和 toRefs 是Vue3中的响应式转换工具函数 toRef: 不影响源对象的情况下&#x…

【数据结构】AVLTree实现详解

目录 一.什么是AVLTree 二.AVLTree的实现 1.树结点的定义 2.类的定义 3.插入结点 ①按二叉搜索树规则插入结点 ②更新平衡因子 更新平衡因子情况分析 ③判断是否要旋转 左单旋 右单旋 左右单旋 右左双旋 4.删除、查找和修改函数 查找结点 三.测试 1.判断是否是搜索树 …

java SpringData JPA中getOne and findById区别

在Spring Data JPA中&#xff0c;getOne和findById方法都用于根据ID获取实体&#xff0c;但它们的行为有所不同&#xff1a; 1、findById(ID id) Optional<User> optionalUser userRepository.findById(userId);if (optionalUser.isPresent()) {User user optio…

面试题-Vue2和Vue3的区别

文章目录 1. 响应式系统2. 组合式 API (Composition API)3. Fragment (碎片)4. Teleport (传送门) 5. 性能改进6. 移除或改变的功能7. 构建工具8. TypeScript 支持 Vue 2 和 Vue 3 之间存在许多重要的区别&#xff0c;这些区别涵盖了性能、API 设计、组合式 API&#xff08;Com…

AndroidStudio无法识别连接夜神模拟器

方法一(无法从根本上解决) ①进入夜神模拟器安装路径下的bin路径(安装路径可以带有中文路径) ②打开cmd窗口,输入以下代码(一定要打开模拟器) nox_adb.exe connect 127.0.0.1:62001 方法二(根本上解决) 原因:Android Studio的adb版本与夜神模拟器的adb版本不一致 ①打开And…

技术架构的发展

技术架构的演进 主要方向&#xff1a; ​ 1.提高单位时间内的吞吐量&#xff0c;提高并发度&#xff1b; ​ 2.对应用服务代码进行解耦合&#xff0c;使得开发效率得到提高&#xff1b; ​ 3.运维成本降低&#xff1b; ​ 4.成本降低&#xff0c;如购买云厂商资源&#xf…