当前位置: 首页 > news >正文

tmpfs的监控筛选/dev/shm下的shmem创建

一、背景

在一个比较注重性能的系统上,共享内存的使用肯定非常普遍。为了能更好的了解系统里共享内存的使用,比如创建、删除等操作,我们是可以对其进行监控的。

这篇博客以共享内存的创建监控为例来介绍如何监控共享内存。

这里有一个概念就是/dev/shm下的文件,是放在内存上的文件,这个/dev/shm如下面的df -h命令可以看到,它是一个tmpfs文件系统,而系统上的tmpfs文件系统其实有很多,/dev/shm是其中一个。我们其实在监控共享内存时,一般来说都是只感兴趣/dev/shm下的也就是shm_open这套shmem接口来创建的共享内存文件。

在下面第二章里,我们贴出改动源码和结果展示,在第三章里,我们给出源码分析和相关细节分析。

二、源码和结果展示

2.1 内核shmem.c里的改动部分

在内核shmem.c里增加下面这段代码:


static u32 _enable_output_path = 0;void shmem_set_enable_output_path(void) {_enable_output_path = 1;
}
EXPORT_SYMBOL_GPL(shmem_set_enable_output_path);void shmem_set_disable_output_path(void) {_enable_output_path = 0;
}
EXPORT_SYMBOL_GPL(shmem_set_disable_output_path);#include <linux/blk_types.h>
#include <linux/blkdev.h>#include <linux/fs.h>
#include <linux/mount.h>#if 0
void print_superblock_root_path(struct super_block *sb) {struct dentry *root_dentry = sb->s_root;char path_buffer[256];struct path root_path;root_path.dentry = root_dentry;root_path.mnt = root_dentry->d_sb->s_root->mnt; // 获取挂载点if (d_path(&root_path, path_buffer, sizeof(path_buffer)) < 0) {printk(KERN_ERR "Failed to get path\n");} else {printk(KERN_INFO "Root path: %s\n", path_buffer);}
}
#endifextern struct dentry* get_dentry_by_sb_currns(struct super_block *sb);static struct super_block *_psb_devshm = NULL;int outputfullpath(const char* i_prefix, struct inode *i_inode, struct dentry* i_dentry)
{struct dentry *dentry;char *buffer, *buffer_mount1, *buffer_mount2, *buffer_mount3, *path;buffer = (char *)__get_free_page(GFP_KERNEL);if (!buffer)return -ENOMEM;buffer_mount1 = (char *)__get_free_page(GFP_KERNEL);if (!buffer_mount1)return -ENOMEM;buffer_mount2 = (char *)__get_free_page(GFP_KERNEL);if (!buffer_mount2)return -ENOMEM;buffer_mount3 = (char *)__get_free_page(GFP_KERNEL);if (!buffer_mount3)return -ENOMEM;if (_psb_devshm) {if (i_inode->i_sb != _psb_devshm) {printk("not /dev/shm!\n");goto free_label;}}hlist_for_each_entry(dentry, &i_inode->i_dentry, d_u.d_alias) {path = dentry_path_raw(dentry, buffer, PAGE_SIZE);if (IS_ERR(path)){continue;   }{struct dentry* de = get_dentry_by_sb_currns(i_inode->i_sb);char *path1 = dentry_path_raw(de, buffer_mount1, PAGE_SIZE);char *path2 = NULL;char *path3 = NULL;//printk("path1 = %s\n", path1);if (de->d_sb) {if (strcmp(path1, "/") != 0) {de = get_dentry_by_sb_currns(de->d_sb);path2 = dentry_path_raw(de, buffer_mount2, PAGE_SIZE);//printk("path2 = %s\n", path2);if (de->d_sb) {if (strcmp(path2, "/") != 0) {de = get_dentry_by_sb_currns(de->d_sb);path3 = dentry_path_raw(de, buffer_mount3, PAGE_SIZE);//printk("path3 = %s\n", path3);}else {path2 = NULL;}}}else {path1 = NULL;}}else {goto free_label;}if (path1 && path2) {if ((strcmp(path2, "/dev") == 0) && (strcmp(path1, "/shm") == 0)) {if (strcmp(path3, "/") == 0) {printk("[/dev/shm][%s]dentry name = %s , path = %s, i_dentry=%s, i_dentry->d_parent.name=%s"" sb->s_root.name=%s (d_parent==sb->s_root)[%u]\n", i_prefix, dentry->d_name.name, path, i_dentry->d_name.name, i_dentry->d_parent->d_name.name, i_inode->i_sb->s_root->d_name.name,(i_dentry->d_parent == i_inode->i_sb->s_root)?1:0);_psb_devshm = i_inode->i_sb;goto free_label;}}}// if (path2) {//     printk("dentry name = %s%s%s\n", path2, path1, path);// }// else if (path1) {//     printk("dentry name = %s%s\n", path1, path);// }// else {//     printk("dentry name = %s\n", path);// }}}free_label:free_page((unsigned long)buffer);free_page((unsigned long)buffer_mount1);free_page((unsigned long)buffer_mount2);free_page((unsigned long)buffer_mount3);//spin_unlock(&inode->i_lock);return 0;
}

然后在shmem.c里的shmem_mknod函数里增加下面这段红框部分的代码:

另外,和之前的博客 获取inode的完整路径包含挂载的路径_内核如何通过inode获取完整路径-CSDN博客 里增加在namespace.c里 3.1 一节里讲的内容一样,增加了下面这个函数:

struct dentry* get_dentry_by_sb_currns(struct super_block *sb)
{struct mnt_namespace *mnt_ns = current->nsproxy->mnt_ns;struct mount *mnt;struct dentry* dentry = NULL;lock_mount_hash();list_for_each_entry(mnt, &mnt_ns->list, mnt_list) {if (mnt->mnt.mnt_sb == sb) {dentry = mnt->mnt_mountpoint;break;}}unlock_mount_hash();return dentry;
}
EXPORT_SYMBOL_GPL(get_dentry_by_sb_currns);

2.2 内核模块用来启动/关闭shmem的这个调试判断和打印

#include <linux/module.h>
#include <linux/capability.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/errno.h>
#include <linux/stddef.h>
#include <linux/lockdep.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <trace/events/workqueue.h>
#include <linux/sched/clock.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/tracepoint.h>
#include <trace/events/osmonitor.h>
#include <trace/events/sched.h>
#include <trace/events/irq.h>
#include <trace/events/kmem.h>
#include <linux/ptrace.h>
#include <linux/uaccess.h>
#include <asm/processor.h>
#include <linux/sched/task_stack.h>
#include <linux/nmi.h>
#include <asm/apic.h>
#include <linux/version.h>
#include <linux/sched/mm.h>
#include <asm/irq_regs.h>
#include <linux/kallsyms.h>
#include <linux/kprobes.h>MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhaoxin");
MODULE_DESCRIPTION("Module for kernel get time.");
MODULE_VERSION("1.0");extern void shmem_set_enable_output_path(void);
extern void shmem_set_disable_output_path(void);static int __init testtmpfs_init(void)
{shmem_set_enable_output_path();return 0;
}static void __exit testtmpfs_exit(void)
{shmem_set_disable_output_path();
}module_init(testtmpfs_init);
module_exit(testtmpfs_exit);

2.3 结果展示

我们先在/dev/shm里创建文件夹和创建新的文件都可以打印出加的调试打印:

如果我们自己mount一个tmpfs的分区,然后在里面创建文件并不会打印出/dev/shm目录下才会打印的上图里的打印,而是打印下图里的not /dev/shm字样:

三、源码分析和相关细节分析

3.1 tmpfs文件系统和shmem接口的应用

shmem.c文件是服务于系统里的所有tmpfs文件系统里的操作。而tmpfs系统在系统里的情况非常普遍:

而我们感兴趣的往往是/dev/shm这样的使用shm的接口的程序应用,有关的例子如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>           // For O_* constants
#include <sys/mman.h>       // For shm_open, mmap
#include <unistd.h>         // For close
#include <sys/stat.h>       // For mode constants
#include <sys/types.h>
#include <errno.h>int main() {const char *name = "/my_shm"; // 共享内存的名称const size_t size = 1024*1024*1024;      // 共享内存的大小int shm_fd;                    // 共享内存文件描述符void *ptr;                     // 指向共享内存的指针// 创建共享内存对象shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);if (shm_fd == -1) {perror("shm_open");exit(EXIT_FAILURE);}// 调整共享内存的大小if (ftruncate(shm_fd, size) == -1) {perror("ftruncate");exit(EXIT_FAILURE);}// 将共享内存映射到进程的地址空间ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);if (ptr == MAP_FAILED) {perror("mmap");exit(EXIT_FAILURE);}getchar();// 锁定共享内存区域中的页if (mlock(ptr, size) != 0) {perror("mlock");exit(EXIT_FAILURE);}getchar();// 写入数据到共享内存sprintf((char*)ptr, "Hello, Shared Memory!");// 读取数据printf("Data from shared memory: %s\n", (char *)ptr);// 解锁共享内存区域if (munlock(ptr, size) != 0) {perror("munlock");exit(EXIT_FAILURE);}// 解除映射if (munmap(ptr, size) == -1) {perror("munmap");exit(EXIT_FAILURE);}// 关闭共享内存对象if (close(shm_fd) == -1) {perror("close");exit(EXIT_FAILURE);}// 删除共享内存对象if (shm_unlink(name) == -1) {perror("shm_unlink");exit(EXIT_FAILURE);}return 0;
}

3.2 shmem.c里的shmem_mknod函数

tmpfs系统下的创建文件夹和创建文件的操作都会走到shmem_mknod函数里来,如下图依次是创建文件夹和创建文件的函数shmem_mkdir和shmem_create,这两个函数最终都是调用的shmem_mknod函数:

所以,我们在shmem_mknod函数里加监测逻辑是能覆盖tmpfs文件系统里的创建文件夹和创建文件的行为。

3.3 shmem.c里的shmem_link和shmem_symlink

shmem.c里还有一些其他接口,如下图里的shmem_link是指硬链接,shmem_symlink是指软链接:

有关硬链接和软链接及相关的inode,dentry的实验见之前的博客 关于inode,dentry结合软链接及硬链接的实验-CSDN博客。

3.4 shmem_mknod函数里增加的“判断是不是/dev/shm下的mknod事件”的逻辑

我们在shmem_mknod里增加了判断逻辑,检查是否是/dev/shm下的mknod事件,用的依次判断是否是/dev和/shm这两级super_block的mnt_mountpoint,而获取mnt_mountpoint的这块核心逻辑在之前的博客 获取inode的完整路径包含挂载的路径_内核如何通过inode获取完整路径-CSDN博客 里进行了分析:

在shmem.c里使用了该get_dentry_by_sb_currns函数进行了几级mountpoint的dentry的记录,然后判断完整的mountpoint的dentry链是否是/dev/shm:

如果判断到是/dev/shm这个完整路径,就记录下来这个super_block指针:

这样,接下来的判断就会更加快了:

相关文章:

tmpfs的监控筛选/dev/shm下的shmem创建

一、背景 在一个比较注重性能的系统上&#xff0c;共享内存的使用肯定非常普遍。为了能更好的了解系统里共享内存的使用&#xff0c;比如创建、删除等操作&#xff0c;我们是可以对其进行监控的。 这篇博客以共享内存的创建监控为例来介绍如何监控共享内存。 这里有一个概念…...

如果你在使用 Ubuntu/Debian:使用 apt 安装 OpenSSH

情况 1&#xff1a;如果你在使用 Ubuntu/Debian&#xff1a; 使用 apt 安装 OpenSSH&#xff1a; bash 复制 sudo apt update sudo apt install openssh-server 完成后检查 SSH 服务状态&#xff1a; bash 复制 sudo systemctl status ssh 情况 2&#xff1a;如果你在使用 Ce…...

设计模式每日硬核训练 Day 11:适配器模式(Adapter Pattern)完整讲解与实战应用

&#x1f504; 回顾 Day 10&#xff1a;模板方法模式小结 在 Day 10 中&#xff0c;我们学习了模板方法模式&#xff1a; 它用于定义流程的“骨架”&#xff0c;将固定步骤放在父类&#xff0c;具体实现交给子类完成。实现了“统一流程 差异化行为”的复用范式。 而今天&am…...

xAI Elasticsearch 集群架构解析:索引数据规模与分片优化实践

Elasticsearch&#xff08;ES&#xff09;作为分布式搜索和分析引擎&#xff0c;是 xAI 构建高性能数据处理系统的基石。xAI 的业务场景&#xff0c;如实时日志分析、模型训练数据检索和用户行为分析&#xff0c;要求 Elasticsearch 集群兼顾高吞吐写入、低延迟查询和动态扩展能…...

[c语言日寄]时间复杂度

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…...

快速幂(蓝桥杯)

1. 递归实现 递归方法通过将问题分解为更小的子问题来实现。具体步骤如下&#xff1a; 如果指数 b 为 0&#xff0c;返回 1。 如果 b 是偶数&#xff0c;则递归计算 (a^2)b/2。 如果 b 是奇数&#xff0c;则递归计算 a⋅(a^2)(b−1)/2。 伪代码&#xff1a; function fas…...

[Python基础速成]2-模块与包与OOP

上篇➡️[Python基础速成]1-Python规范与核心语法 目录 Python模块创建模块与导入属性__name__dir()函数标准模块 Python包类类的专有方法 对象继承多态 Python模块 Python 中的模块&#xff08;Module&#xff09;是一个包含 Python 定义和语句的文件&#xff0c;文件名就是模…...

Spring AOP 学习笔记 之 常用注解

0 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>3.4.2</version></dependency> 要在springboot中启用AOP&#xff0c;需要引入spring-boot-…...

JVM——运行时数据区

目录 Class装载到JVM的过程 装载&#xff08;load&#xff09;——查找和导入class文件 正文------------------- Run-time Data Areas 运行时数据区 Method Area 方法区 Heap 堆 Java Virtual Machine Stacks&#xff08;Java虚拟机栈&#xff09; The PC Register 程…...

Conda 入门指令教程

Conda 入门指令教程 Conda 是一个强大的包和环境管理工具&#xff0c;广泛应用于数据科学和机器学习项目中。本文将介绍 Conda 的常用指令&#xff0c;帮助你快速上手。 1. Conda 基础操作 查看 Conda 版本 conda --version显示当前安装的 Conda 版本。 更新 Conda conda…...

基于STM32、HAL库的MAX14830总线转UART驱动程序设计

一、简介: MAX14830是一款四通道UART扩展器,通过SPI或I2C接口与微控制器通信。主要特性包括: 4个独立的全双工UART通道 可编程波特率(最高达12Mbps) 每个通道有128字节的发送和接收FIFO 支持硬件和软件流控制 可配置的GPIO引脚 工作电压:1.7V至5.5V 低功耗模式 二、硬件…...

x-cmd install | jellex - 用 Python 语法在终端里玩转 JSON 数据!

目录 核心功能与特点安装优势亮点适用场景 还在为命令行下处理 JSON 数据烦恼吗&#xff1f;jellex 来了&#xff01;它是一款基于终端的交互式 JSON 和 JSON Lines 数据处理工具&#xff0c;让你用熟悉的 Python 语法&#xff0c;轻松过滤、转换和探索 JSON 数据。 核心功能与…...

2025天梯赛 L2专项训练

L2-049 鱼与熊掌 - 团体程序设计天梯赛-练习集 思路就是模拟&#xff0c;正常写就完事 #include<bits/stdc.h> using namespace std; int main() {int a, b;cin >> a >> b;vector<vector<int>>arr(a, vector<int>(0));for (int i 0; i &…...

214、【数组】下一个排列(Python)

题目描述 原题链接&#xff1a;31. 下一个排列 思路 从后往前&#xff0c;找到第一个小于右侧集合的数&#xff0c;从右侧集合中找到一个比该数大的最小的数替换上去。 然后&#xff0c;将右侧集合从小到排列&#xff0c;就为当前排列中&#xff0c;下一个排列的数。 代码实…...

Why does Java‘s hashCode() in String use 31 as a multiplier?

HashCode 为什么使用 31 作为乘数&#xff1f; 1. 固定乘积 31 在这用到了2. 来自 stackoverflow 的回答3. Hash 值碰撞概率统计3.1 读取单词字典表3.2 Hash 计算函数3.3 Hash 碰撞概率计算封装碰撞统计信息的类3.4 针对一组乘数&#xff0c;分别计算碰撞率3.5 碰撞结果可视化3…...

如何将一个8s的接口优化到500ms以下

最近换了个工作&#xff0c;刚入职就接了个活--优化公司自营app的接口性能&#xff0c;提升用户体验。 刚开始还以为是1s优化到500ms这种&#xff0c;或者500ms优化到200ms的接口&#xff0c;感觉还挺有挑战的。下好app体验了一下。好家伙&#xff0c;那个慢已经超过了我的忍耐…...

如何保证本地缓存和redis的一致性

1. Cache Aside Pattern&#xff08;旁路缓存模式&#xff09;​​ ​核心思想​&#xff1a;应用代码直接管理缓存与数据的同步&#xff0c;分为读写两个流程&#xff1a; ​读取数据​&#xff1a; 先查本地缓存&#xff08;如 Guava Cache&#xff09;。若本地未命中&…...

30天学Java第十天——反射机制

反射机制 反射机制是 Java 语言中的一个重要特性&#xff0c;它允许程序在运行时动态地获取类的信息&#xff08;如类的属性、方法和构造器等&#xff09;&#xff0c;并且可以操作这些信息。 反射机制在某些情况下非常有用&#xff0c;例如开发框架、库&#xff0c;或者需要进…...

Nodejs Express框架

参考&#xff1a;Node.js Express 框架 | 菜鸟教程 第一个 Express 框架实例 接下来我们使用 Express 框架来输出 "Hello World"。 以下实例中我们引入了 express 模块&#xff0c;并在客户端发起请求后&#xff0c;响应 "Hello World" 字符串。 创建 e…...

视频设备轨迹回放平台EasyCVR打造货运汽车安全互联网视频监控与管理方案

一、背景介绍 随着互联网发展&#xff0c;货运中介平台大量涌现&#xff0c;行业纠纷也随之增多。尽管当前平台APP具备录音和定位功能&#xff0c;但货物交易流程的全方位监控仍无法实现。主流跟踪定位服务大部分聚焦货物轨迹与车辆定位&#xff0c;尚未实现货物全程可视化监控…...

玩转Docker | 使用Docker部署Docmost文档管理系统

玩转Docker | 使用Docker部署Docmost文档管理系统 前言一、Docmost介绍Docmost 简介Docmost 特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署Docmost服务下载镜像编辑部署文件创建容器检查容器状态检查服务端口安全设置四、访问Docmost服务访问Docmos…...

docker方式项目部署(安装容器组件+配置文件导入Nacos+dockerCompose文件创建管理多个容器+私有镜像仓库Harbor)

基于docker的部署 服务器主机ip 192.168.6.131 安装组件 安装redis docker pull redis:7.0.10#在宿主机上/var/lib/docker/volumes/redis-config/_data/目录下创建一个redis配置文件 vim redis.conf#内容如下 appendonly yes #开启持久化 port 6379 #requirepass 1234 #密码…...

基于OpenCV与PyTorch的智能相册分类器全栈实现教程

引言&#xff1a;为什么需要智能相册分类器&#xff1f; 在数字影像爆炸的时代&#xff0c;每个人的相册都存储着数千张未整理的照片。手动分类不仅耗时&#xff0c;还容易遗漏重要瞬间。本文将手把手教你构建一个基于深度学习的智能相册分类系统&#xff0c;实现&#xff1a;…...

C++中string库常用函数超详细解析与深度实践

目录 一、引言 二、基础准备&#xff1a;头文件与命名空间 三、string对象的创建与初始化(基础&#xff09; 3.1 直接初始化 3.2 动态初始化&#xff08;空字符串&#xff09; 3.3 基于字符数组初始化 3.4 重复字符初始化 四、核心函数详解 4.1 字符串长度相关 4.1.1 …...

数据结构(3)

实验步骤&#xff1a; 任务&#xff1a;要求使用自定义函数来实现 输入一段文本&#xff0c;统计每个字符出现的次数&#xff0c;按照字符出现次数从多到少&#xff0c;依次输出&#xff0c;格式如下&#xff1a; 字符1-个数 字符2-个数 ...... 解题思路&#xff1a; 构建结构体…...

【C++教程】使用printf语句实现进制转换

在C语言中&#xff0c;printf 函数可以直接实现部分进制转换功能&#xff0c;通过格式说明符&#xff08;format specifier&#xff09;快速输出不同进制的数值。以下是详细使用方法及示例代码&#xff1a; 一、printf 原生支持的进制转换 1. 十进制、八进制、十六进制转换 #…...

el-dialog设置append-to不生效;el-dialog设置挂载层级

文章目录 一、场景二、注意点1. append-to-body何时为true2.设置层级&#xff0c;遮罩层大小不生效3.相关代码 三、ElMessageBox遮罩层 效果&#xff1a; 一、场景 正常情况下&#xff0c;el-dialog的弹框是挂载在body下的&#xff0c;导致我们会有修改样式或者修改弹框的遮罩…...

互联网软件开发自动化平台 的多维度对比分析,涵盖架构、功能、适用场景、成本等关键指标

以下是关于 互联网软件开发自动化平台 的详细解析&#xff0c;涵盖其核心概念、主流平台的功能、架构设计、适用场景及对比分析&#xff1a; 一、自动化平台的定义与核心目标 自动化平台&#xff08;如CI/CD平台&#xff09;是用于 持续集成&#xff08;CI&#xff09; 和 持续…...

UE5 制作方块边缘渐变边框效果

该效果基于之前做的&#xff08;https://blog.csdn.net/grayrail/article/details/144546427&#xff09;进行修改得到&#xff0c;思路也很简单&#xff1a; 1.打开实时预览 1.为了制作时每个细节调整方便&#xff0c;勾选Live Update中的三个选项&#xff0c;开启实时预览。…...

深入探究 GRU 模型:梯度爆炸问题剖析

在深度学习领域&#xff0c;循环神经网络&#xff08;RNN&#xff09;及其变体在处理序列数据时展现出了强大的威力。其中&#xff0c;门控循环单元&#xff08;GRU&#xff09;作为 RNN 的一种进阶架构&#xff0c;备受关注。今天&#xff0c;咱们就来深入聊聊 GRU 模型&#…...

生成对抗网络(GAN)原理详解

生成对抗网络&#xff08;GAN&#xff09;原理详解 1. 背景 生成对抗网络&#xff08;Generative Adversarial Network, GAN&#xff09;由 Ian Goodfellow 等人于 2014 年提出&#xff0c;是一种通过对抗训练生成高质量数据的框架。其核心思想是让两个神经网络&#xff08;生…...

CFD中的动量方程非守恒形式详解

在计算流体力学&#xff08;CFD&#xff09;中&#xff0c;动量方程可以写成守恒形式和非守恒形式&#xff0c;两者在数学上等价&#xff0c;但推导方式和应用场景不同。以下是对非守恒形式的详细解释&#xff1a; 1. 动量方程的守恒形式 首先回顾守恒形式的动量方程&#xff…...

AIoT 智变浪潮演讲实录 | 刘浩然:让硬件会思考:边缘大模型网关助力硬件智能革新

4 月 2 日&#xff0c;由火山引擎与英特尔联合主办的 AIoT “智变浪潮”技术沙龙在深圳成功举行&#xff0c;活动聚焦 AI 硬件产业的技术落地与生态协同&#xff0c;吸引了芯片厂商、技术方案商、品牌方及投资机构代表等 700 多位嘉宾参会。 会上&#xff0c;火山引擎边缘智能高…...

4.B-树

一、常见的查找方式 顺序查找 O(N) 二分查找 O(logN)(要求有序和随机访问) 二叉搜索树 O(N) 平衡二叉搜索树(AVL树和红黑树) O(logN) 哈希 O(1) 考虑效率和要求而言,正常选用 平衡二叉搜索树 和 哈希 作为查找方式。 但这两种结构适合用于数据量相对不是很大,能够一次性…...

怎么看英文论文 pdf沉浸式翻译

https://arxiv.org/pdf/2105.09492 Immersive Translate Xournal打开...

计算机三级第一章:信息安全保障概述(以时间节点推进的总结)

淡蓝色为必背内容 第一阶段:电讯技术的发明19世纪30年代:电报电话的发明 1835年:莫尔斯(Morse)发明了电报 1837年:莫尔斯电磁式有线电报问世 1878年:人工电话交换局出现 1886年:马可尼发明了无线电报机 1876年:贝尔(Bell)发明了电话机 1892年,史瑞桥自动交换…...

车载软件架构 ---单个ECU的AUTOSAR开发流程

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…...

【场景应用7】在TPU上使用Flax/JAX对Transformers模型进行语言模型预训练

在本笔记本中,我们将展示如何使用Flax在TPU上预训练一个🤗 Transformers模型。 这里将使用GPT2的因果语言建模目标进行预训练。 正如在这个基准测试中所看到的,使用Flax/JAX在GPU/TPU上的训练通常比使用PyTorch在GPU/TPU上的训练要快得多,而且也可以显著降低成本。 Fla…...

C++运算符重载全面总结

C运算符重载全面总结 运算符重载是C中一项强大的特性&#xff0c;它允许程序员为自定义类型定义运算符的行为。以下是关于C运算符重载的详细总结&#xff1a; 一、基本概念 1. 什么是运算符重载 运算符重载是指为自定义类型&#xff08;类或结构体&#xff09;重新定义或重…...

PTA | 实验室使用排期

目录 题目&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 样例解释&#xff1a; 代码&#xff1a; 无注释版&#xff1a; 有注释版&#xff1a; 题目&#xff1a; 受新冠疫情影响&#xff0c;当前大家的活动都…...

3.7 字符串基础

字符串 &#xff08;str&#xff09;&#xff1a;和列表用法基本一致 1.字符串的创建 -str转换(字符串&#xff0c;可用于将其他字符类型转换为字符串) -单引号 双引号 三引号 2.索引 3.字符串的切片 4.字符串的遍历 5.字符串的格式化 6.字符串的运算符 7.字符串的函数 #…...

《 C++ 点滴漫谈: 三十三 》当函数成为参数:解密 C++ 回调函数的全部姿势

一、前言 在现代软件开发中&#xff0c;“解耦” 与 “可扩展性” 已成为衡量一个系统架构优劣的重要标准。而在众多实现解耦机制的技术手段中&#xff0c;“回调函数” 无疑是一种高效且广泛使用的模式。你是否曾经在编写排序算法时&#xff0c;希望允许用户自定义排序规则&a…...

16bit转8bit的常见方法(图像归一化)

文章目录 16-bit转8-bit的常用方法一、数据类型转换&#xff1a;image.astype(np.uint8) —— 若数值 x 超出 0-255 范围&#xff0c;则取模运算。如&#xff1a;x 600 % 256 88二、截断函数&#xff1a;np.clip().astype(np.uint8) —— 若数值 x 超出 0-255 范围&#xff0…...

消息中间件kafka,rabbitMQ

在分布式系统中,消息中间件是实现不同组件之间异步通信的关键技术。Kafka 和 RabbitMQ 是两个非常流行的消息中间件系统,它们各自有着不同的特点和应用场景。下面将分别介绍 Kafka 和 RabbitMQ,并讨论它们在消息队列中的使用。 一、Kafka (Apache Kafka) 主要特点: 高吞吐…...

C语言编译预处理3

条件编译&#xff1a;是对源程序的一部分指定编译条件&#xff0c;满足条件进行编译否则不编译。 形式1 #indef 标识符 程序段1 #else 程序段2 #endif 标识符已经被定义用#ifdef #include <stdio.h>// 可以通过注释或取消注释下面这行来控制是否定义 DEBUG 宏 // …...

数据结构·树

树的特点 最小连通图 无环 有且只有 n − 1 n-1 n−1 条边 树的建立方式 顺序存储 只适用于满n叉树&#xff0c;完全n叉树 1<<n 表示结点 2 n 2^n 2nP4715 【深基16.例1】淘汰赛 void solve() {cin >> n;for (int i 0; i<(1<<n); i) {cin >&g…...

队列的各种操作实现(数据结构C语言多文件编写)

1.先创建queue.h声明文件(Linux命令&#xff1a;touch queue.h)。编写函数声明如下(打开文件 Linux 操作命令&#xff1a;vim queue.h): //头文件 #ifndef __QUEUE_H__ #define __QUEUE_H__ //队列 typedef struct queue{int* arr;int in;int out;int cap;int size; }queue_t;…...

48V/2kW储能电源纯正弦波逆变器详细设计方案-可量产

48V/2kW储能电源纯正弦波逆变器详细设计方案 1.后级驱动电路图 2.前级驱动电路图 3.功率表电路原理图 4.功率板BOM: 5.后级驱动BOM 6.前级驱动BOM...

[redis进阶二]分布式系统之主从复制结构(2)

目录 一 redis的拓扑结构 (1)什么是拓扑 (2)⼀主⼀从结构 (3)⼀主多从结构 (4)树形主从结构 (5)三种拓扑结构的优缺点,以及适用场景 二 redis的复制原理 (1)复制过程 (2)数据同步psync replicationid/replid (复制id)(标注同步的数据来自哪里:数据来源) offset (偏移…...

Playwright多语言生态:跨Python_Java_.NET的统一采集方案

一、问题背景&#xff1a;爬虫多语言割裂的旧时代 在大规模数据采集中&#xff0c;尤其是学术数据库如 Scopus&#xff0c;开发者常遇到两个经典问题&#xff1a; 技术语言割裂&#xff1a;Python开发人员使用Selenium、requests-html等库&#xff1b;Java阵营使用Jsoup或Htm…...