驱动-内核空间和用户空间数据交换
内核空间与用户控件数据交换
前面了解的字符设备中对 file_operations 结构体的进行了填充, 该
结构体的每一个成员都对应着一个系统调用, 例如 read、 write 等, 在字符设备相关的文章中有实验过对
调用函数进行了标志打印, 并没有真正实现设备的读写功能。 这里需要实现的功能其实就是内核空间和用户控件之间的数据交换
文章目录
- 理解概念:内核空间与用户空间
- 参考资料
- 用户空间和内核空间数据交换
- 用户空间数据复制到内核空间 copy_from_user
- 数据从内核空间拷贝到用户空间copy_to_user
- 实验
- 源码程序 file.c
- 方法 copy_to_user
- 方法 copy_from_user
- 编译文件 Makefile
- 测试程序
- 源码程序分析
- 加载驱动 insmod file.ko
- 执行程序 ./appfile
- 总结
理解概念:内核空间与用户空间
Linux 系统将可访问的内存空间分为了两个部分, 一部分是内核空间, 一部分是用户空间。
操作系统和驱动程序运行在内核空间(内核态) , 应用程序运行在用户空间(用户态) 。
那么为什么要区分用户空间和内核空间呢?
(1) 内核空间中的代码控制了硬件资源, 用户空间中的代码只能通过内核暴露的系统调
用接口来使用系统中的硬件资源, 这样的设计可以保证操作系统自身的安全性和稳定性。
(2) 从另一方面来说, 内核空间的代码更偏向于系统管理, 而用户空间中的代码更偏重
业务逻辑实现, 俩者的分工不同。
硬件资源管理都是在内核空间完成的, 应用程序无法直接对硬件进行操作, 只能通过调用
相应的内核接口来完成相应的操作。 比如应用程序要对磁盘上的一个文件进行读取, 应用程序
可以向内核发起一个“系统调用” 申请——我要读取磁盘上的文件。 这个过程其实是通过一个
特殊的指令让进程从用户态进入到了内核态。 在内核空间中, CPU 可以执行任何命令, 包括
从磁盘上读取数据, 具体过程是先把数据读取到内核空间中, 然后再把数据拷贝到用户空间并
从内核态切换到用户态。 此时应用程序已经从系统调用中返回并拿到了想要的数据, 可以继续
往下执行了。
进程只有从用户空间切换到内核空间才可以使用系统的硬件资源, 切换的方式有三种: 系
统调用, 软中断, 硬中断, 如下图:
参考资料
字符设备的基础知识一定要了解,都是关联的知识点
申请字符设备号
注册字符设备
创建字符设备节点
字符设备驱动框架
杂项设备
用户空间和内核空间数据交换
内核空间和用户空间的内存是不能互相访问的。 但是很多应用程序都需要和内核进行数据
的交换, 例如应用程序使用 read 函数从驱动中读取数据, 使用 write 函数向驱动中写数据, 上
述功能就需要使用 copy_from_user 和 copy_to_user 俩个函数来完成。 copy_from_user 函数是将
用户空间的数据拷贝到内核空间。 copy_to_user 函数是将内核空间的数据拷贝到用户空间。
这俩个函数定义在了 kernel/include/linux/uaccess.h 文件下
用户空间数据复制到内核空间 copy_from_user
copy_from_user 用于将数据从用户空间复制到内核空间。
unsigned long copy_from_user(void *to, const void __user *from, unsigned long n);
参数说明
- to: 内核空间的目标地址
- from: 用户空间的源地址
- n: 要复制的字节
使用示例
char kernel_buf[BUFSIZE];
if (copy_from_user(kernel_buf, user_buf, count)) {// 处理错误return -EFAULT;
}
数据从内核空间拷贝到用户空间copy_to_user
copy_to_user 用于将数据从内核空间复制到用户空间。 函数原型如下:
unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);
- to: 用户空间的目标地址
- from: 内核空间的源地址
- n: 要复制的字节数
实验
源码程序 file.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>static dev_t dev_num;//定义dev_t类型(32位大小)的变量dev_num
static int major; //定义int类型的主设备号major
static int minor;//定义int类型的 次设备号minor
static struct cdev cdev_test; //定义struct cdev 类型结构体变量cdev_test,表示要注册的字符设备
struct class *class_test;//定于struct class *类型结构体变量class_test,表示要创建的类
struct device *device; //设备/*打开设备函数*/
static int chrdev_open(struct inode *inode, struct file *file)
{printk("This is chrdev_open \n");return 0;
}static ssize_t chrdev_read(struct file *file,char __user *buf, size_t size, loff_t *off)
{/*本章实验重点******/char kbuf[32] = "This is read from kernel";//定义内核空间数据// copy_to_user:内核空间向用户空间传数据if (copy_to_user(buf, kbuf, strlen(kbuf)) != 0) {printk("copy_to_user error\r\n"); //打印copy_to_user函数执行失败return -1;}printk("This is cdev_test_read\r\n");return 0;
}/*向设备写入数据函数*/
static ssize_t chrdev_write(struct file *file,const char __user *buf,size_t size,loff_t *off)
{/*本章实验重点******/char kbuf[32] = {0}; //定义写入缓存区kbufif (copy_from_user(kbuf, buf, size) != 0) // copy_from_user:用户空间向内核空间传数据{printk("copy_from_user error\r\n");//打印copy_from_user函数执行失败return -1;}printk("This is cdev_test_write\r\n");printk("kbuf is %s\r\n", kbuf);return 0;
}
static int chrdev_release(struct inode *inode, struct file *file)
{return 0;
}static struct file_operations cdev_test_ops = {.owner=THIS_MODULE,//将owner字段指向本模块,可以避免在模块的操作正在被使用时卸载该模块.open = chrdev_open,//将open字段指向chrdev_open(...)函数.read = chrdev_read,//将open字段指向chrdev_read(...)函数.write = chrdev_write,//将open字段指向chrdev_write(...)函数.release = chrdev_release,//将open字段指向chrdev_release(...)函数
};//定义file_operations结构体类型的变量cdev_test_opsstatic int __init chrdev_fops_init(void)//驱动入口函数
{int ret;//定义int类型的变量ret,用来判断函数返回值ret=alloc_chrdev_region(&dev_num,0,1,"chardev_num"); //通过动态方式进行设备号注册if(ret < 0){printk("alloc_chrdev_region is error\n");} printk("alloc_chrdev_region is ok\n");major=MAJOR(dev_num);//通过MAJOR()函数进行主设备号获取minor=MINOR(dev_num);//通过MINOR()函数进行次设备号获取printk("major is %d\n",major);printk("minor is %d\n",minor);使用cdev_init()函数初始化cdev_test结构体,并链接到cdev_test_ops结构体cdev_init(&cdev_test,&cdev_test_ops);cdev_test.owner = THIS_MODULE;//将owner字段指向本模块,可以避免在模块的操作正在被使用时卸载该模块 ret= cdev_add(&cdev_test,dev_num,1);if(ret < 0 ){printk("cdev_add is error\n");}printk("cdev_add is ok\n");class_test = class_create(THIS_MODULE,"class_test");//使用class_create进行类的创建,类名称为class_testdevice_create(class_test,NULL,dev_num,NULL,"device_test");//使用device_create进行设备的创建,设备名称为device_testreturn 0;
}
static void __exit chrdev_fops_exit(void)//驱动出口函数
{cdev_del(&cdev_test);//使用cdev_del()函数进行字符设备的删除unregister_chrdev_region(dev_num,1);//释放字符驱动设备号 device_destroy(class_test,dev_num);//删除创建的设备class_destroy(class_test);//删除创建的类printk("module exit \n");}
module_init(chrdev_fops_init);//注册入口函数
module_exit(chrdev_fops_exit);//注册出口函数
MODULE_LICENSE("GPL v2");//同意GPL开源协议
MODULE_AUTHOR("wang fang chen "); //作者信息
源码分析:
这里省略之前内容关联知识的内容,重点看 内核空间和用户控件数据交换部分内容。
方法 copy_to_user
读取内核空间数据到用户空间,定义了内核空间数据,其实就是驱动程序里面定义了字节数组
char kbuf[32] = “This is read from kernel”;//定义内核空间数据
copy_to_user 方法调用后, copy kbuf 数据到 buf里面去,buf 在方法里面的参数是一个用户空间态指针,这样就传递到用户空间了。
static ssize_t chrdev_read(struct file *file,char __user *buf, size_t size, loff_t *off)
{/*本章实验重点******/char kbuf[32] = "This is read from kernel";//定义内核空间数据// copy_to_user:内核空间向用户空间传数据if (copy_to_user(buf, kbuf, strlen(kbuf)) != 0) {printk("copy_to_user error\r\n"); //打印copy_to_user函数执行失败return -1;}printk("This is cdev_test_read\r\n");return 0;
}
方法 copy_from_user
从用户空间数据copy 数据到内核空间
buf 数据是用户态指针类型,调用 copy_from_user 方法后 kbuf 就有新的数据了,其实其实驱动程序里面的数据就是内核态数据,然后将其打印出来。
/*向设备写入数据函数*/
static ssize_t chrdev_write(struct file *file,const char __user *buf,size_t size,loff_t *off)
{/*本章实验重点******/char kbuf[32] = {0}; //定义写入缓存区kbufif (copy_from_user(kbuf, buf, size) != 0) // copy_from_user:用户空间向内核空间传数据{printk("copy_from_user error\r\n");//打印copy_from_user函数执行失败return -1;}printk("This is cdev_test_write\r\n");printk("kbuf is %s\r\n", kbuf);return 0;
}
编译文件 Makefile
#!/bin/bash
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
obj-m += file.o
KDIR :=/home/wfc123/Linux/rk356x_linux/kernel
PWD ?= $(shell pwd)
all:make -C $(KDIR) M=$(PWD) modulesclean:make -C $(KDIR) M=$(PWD) clean
测试程序
appfile.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[]) // 主函数
{int fd; // 定义 int 类型的文件描述符char buf1[32] = {0}; // 定义读取缓存区 buf1char buf2[32] = "nihao"; // 定义写入缓存区 buf2fd = open("/dev/test", O_RDWR); // 打开字符设备驱动if (fd < 0){perror("open error \n");return fd;}read(fd, buf1, sizeof(buf1)); // 从/dev/test 文件读取数据printf("buf1 is %s \r\n", buf1); // 打印读取的数据write(fd, buf2, sizeof(buf2)); // 向/dev/test 文件写入数据close(fd);return 0;
}
源码程序分析
这里关注read 方法,buf1 用户态数据,读取后 经过系统调用
copy_to_user(buf, kbuf, strlen(kbuf)),内核态数据copy 了一份到用户态 buf1 中,然后打印出来。
需要 aarch64-linux-gnu-gcc 来编译, 输入以下命令, 编译完成以后会生成一个可执行程序
aarch64-linux-gnu-gcc appfile.c -o appfile
生成可执行程序 appfile
加载驱动 insmod file.ko
这里都是以前的基本知识,暂不扩展
执行程序 ./appfile
结果如下: 不正是内核和用户态数据交互结果吗?
总结
- copy_from_user 和 copy_to_user 是 Linux 内核中用于在用户空间和内核空间之间安全传输数据的两个重要函数。
- 内核和用户态数据传递就是通过两个方法调用来实现,回调到用户态其实就是指针传递。
相关文章:
驱动-内核空间和用户空间数据交换
内核空间与用户控件数据交换 前面了解的字符设备中对 file_operations 结构体的进行了填充, 该 结构体的每一个成员都对应着一个系统调用, 例如 read、 write 等, 在字符设备相关的文章中有实验过对 调用函数进行了标志打印, 并没…...
智膳优选 | AI赋能的智慧食堂管理专家 —— 基于飞书多维表格和扣子(Coze)的智能解决方案
智膳优选 | AI赋能的智慧食堂管理专家 基于飞书多维表格和扣子(Coze)的智能解决方案 数据驱动餐饮管理,让每一餐都是营养与经济的完美平衡! “智膳优选”通过整合飞书与Coze,将数据智能引入校园餐饮管理࿰…...
FCOS目标检测
一、模型框架 FCOS采用的网络架构和RetinaNet一样,都是采用FPN架构,如图2所示,每个特征图后是检测器,检测器包含3个分支:classification,regression和center-ness。 对于特征图Fi∈RHWC,其相对…...
Linux中动态加载两个同名so(dlopen动态链接库)
// 当前路径下 ./test1.c int Func1(int a, int b) { return ab; } //编译生成so gcc -fPIC -shared -o libTest.so test1.c // 当前路径的test2文件夹中 ./test2/test2.c int Func1(int a, int b) { return a-b; } //编译生成同名so gcc -fPIC -shared -o …...
直播电商革命:东南亚市场的“人货场”重构方程式
一、人设经济3.0:从流量收割到情感基建 东南亚直播战场正经历从"叫卖式促销"到"沉浸式信任"的质变,新加坡市场成为最佳观察样本: 数据印证趋势:Shopee直播用户日均停留28分钟,超短视频平台&#…...
【CF】Day30——Codeforces Round 824 (Div. 2) C + Codeforces Round 825 (Div. 2) BC1
C. Phase Shift 题目: 思路: 好题,值得多看 这题我们看题目就能想到一个很显然的做法,那就是贪心地把每一个字母换成最前面的没使用过的字母 但是这样直接写是有问题的,因为题目说了最后要让所有的字母成一个换&…...
STM32 模块化开发指南 · 第 2 篇 如何编写高复用的外设驱动模块(以 UART 为例)
本文是《STM32 模块化开发实战指南》的第 2 篇,聚焦于“串口驱动模块的设计与封装”。我们将从一个最基础的裸机 UART 初始化开始,逐步实现:中断支持、环形缓冲收发、模块接口抽象与测试策略,构建一个可移植、可扩展、可复用的 UART 驱动模块。 一、模块化 UART 的设计目标…...
SSRF打靶总结
文章目录 一. PortSwigger1、本地服务器的基本SSRF2、基本的目标不是漏洞机3、Referer标头的外带SSRF4、简单黑名单的SSRF黑名单绕过思路: 5、重定向的SSRF6. 简单的白名单SSRF白名单绕过思路: 二、BWAPP1. SSRF 文件包含漏洞 | 内网探测2. XXE -> S…...
第五章:5.1 ESP32物联网应用 - MQTT协议深度教程
一、MQTT协议简介 1.1 发布/订阅模式 MQTT(Message Queuing Telemetry Transport)是一种轻量级物联网通信协议,采用发布/订阅模式: 发布者(Publisher):发送消息到指定主题(如&…...
c++知识点
高级模板技术45: 模板元编程:这是一种在编译期进行计算和代码生成的技术。通过模板的递归展开、特化等操作,可以实现一些复杂的功能,例如编译期的计算、类型安全的容器等。例如,使用模板元编程可以实现一个编译期计算斐…...
【ChCore Lab 01】Bomb Lab 拆炸弹实验(ARM汇编逆向工程)
文章目录 1. 前言2. 实验代码版本问题3. 关于使用问题4. 宏观分析5. read_line 函数介绍6. phase_0 函数6.1. read_int 函数6.2. 回到 phase_0 函数继续分析6.3. 验证结果 7. phase_1 函数7.2. 验证结果 8. phase_2 函数8.1. read_8_numbers 函数8.2. 回到 phase_2 函数继续分析…...
QStackedWidget讲解
简介 QStackedWidget 类在一次仅显示1个窗口的地方提供一个窗口栈。 头文件:#include qmake:QT widgets 基类:QFrame 属性 count : const int currentIndex : int 公有槽函数 void setCurrentIndex(int index) void setCurrentWidget(QWidget *widget)信号 void current…...
宝马集团加速 ERP 转型和上云之旅
宝马集团(BMW Group)作为全球领先的豪华汽车和摩托车制造商,致力于构建更加智能、绿色、人性化的出行体验。为了支持其全球化、数字化业务战略,宝马集团正在进行大规模的 IT 体系升级和 ERP 云转型。该项目以“RISE with SAP S/4H…...
AutoEval:现实世界中通才机器人操作策略的自主评估
25年3月来自 UC Berkeley 和 Nvidia 的论文“AutoEval: Autonomous Evaluation of Generalist Robot Manipulation Policies in the Real World”。 可规模化且可复现的策略评估一直是机器人学习领域长期存在的挑战。评估对于评估进展和构建更优策略至关重要,但在现…...
ARM Cortex M内存屏障指令__dsb( )和__isb( )
ARM Cortex-M 系列处理器中的 __dsb() 和 __isb() 是内存屏障指令,用于确保内存操作的顺序性和可见性,尤其在涉及外设、多核/多线程、自修改代码或关键系统配置时至关重要。 一,详细说明和典型应用场景 1. __dsb()(Data Synchron…...
deepseek热度已过?
DeepSeek的热度并没有消退,以下是具体表现: 用户使用量和下载量方面 • 日活跃用户量增长:DeepSeek已经成为目前最快突破3000万日活跃用户量的应用程序。 • 应用商店下载量:1月26日,DeepSeek最新推出的AI聊天机器人…...
使用 Datadog 和 Slack Alerts 监控 minikube
为什么要监控 minikube 集群?这是一个不错的练习,可以让你了解 DataDog 的设置过程并探索 K8s 指标产品。 本文将分享我的以下经验: 设置最新的 minikube部署示例应用程序创建 DataDog(试用)帐户使用 Helm 安装 Data…...
深入 Redis 持久化:从原理到企业级应用的全景图
🧠 什么是 Redis 持久化?为什么需要? Redis 是内存型数据库,默认所有数据都存在内存中,一旦断电,数据就会消失。为了避免重要数据丢失,Redis 提供了持久化机制,用于将内存中的数据保…...
NET模式下如何配置虚拟机的IP地址为静态的
1.查看网关: 2.找到虚拟机的网络配置文件 cd ./etc/sysconfig/network-scripts/ vim ifcfg-ens33 3.修改配置 BROWSER_ONLY"no" IPADDR192.168.122.120 NETMASK255.255.255.0 GATEWAY192.168.122.2 DNS18.8.8.8 4.重启网路服务 sudo systemctl rest…...
VMWare Workstation Pro17.6最新版虚拟机详细安装教程(附安装包教程)
目录 前言 一、VMWare虚拟机下载 二、VMWare虚拟机安装 三、运行虚拟机 前言 VMware 是全球领先的虚拟化技术与云计算解决方案提供商,通过软件模拟计算机硬件环境,允许用户在一台物理设备上运行多个独立的虚拟操作系统或应用。其核心技术可提升硬件…...
磐石云智能语音客服系统——技术革新引领服务新体验
在人工智能技术飞速发展的今天,企业对于智能化客户服务的需求日益增长。磐石云智能语音客服系统凭借其前沿技术架构与深度场景适配能力,正在重新定义人机交互的边界。本文将深入解析该系统如何通过技术创新实现服务效率与体验的双重突破。 一、意图识别…...
什么是iPaaS?
在当今数字化时代,企业面临着日益复杂的IT环境和不断增长的业务需求。随着云计算、微服务、物联网等技术的快速发展,企业需要更加高效、灵活且安全的方式来进行数据集成和应用集成。集成平台即服务(iPaaS)应运而生,成为…...
Vue3 中 Pinia 持久化的全面解析和最佳实践
Vue3 中 Pinia 持久化的全面解析 一、Pinia 简介 Pinia 是 Vue 的新一代状态管理库,它提供了简洁的 API,支持 Composition API,并且拥有良好的代码拆分和热更新能力。相比于 Vuex,Pinia 的代码结构更加扁平,易于理…...
蓝桥杯最后一天警告!!!
1.万能头文件 #include <bits/stdc.h> 2.一道题实在一点都不会,直接碰运气骗分 #include <bits/stdc.h> using namespace std;int main() {srand(time(0));printf("%d",rand()%101);//生成一个1到10之间的随机整数,并输出print…...
el-time-picker标签的使用
需求: 实现培训日期,用户可以选择某一天的日期,这个比较简单 <el-form-item label"培训日期" prop"startTime"><el-date-picker clearablev-model"form.startTime"type"date"placeholder…...
Mysql--基础知识点--85.1--Innodb自适应哈希索引
1. 自适应哈希索引的用途 InnoDB 的自适应哈希索引(Adaptive Hash Index, AHI)是 MySQL 数据库引擎中一项智能优化查询性能的功能。其核心作用如下: 加速等值查询 哈希索引通过哈希函数将键映射到固定位置,实现 O(1) 时间复杂度的…...
Matlab 考虑电机激励力的整车垂向七自由度的被动悬架和LQR控制
1、内容简介 Matlab 200-考虑电机激励力的整车垂向七自由度的被动悬架和LQR控制 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...
统一功能处理
SpringBoot统一功能处理 本节目表 1.掌握拦截器的使用,及其原理 2.学习统一数据返回格式和统一异常处理的操作 3.了解一些Spirng的源码 文章目录 SpringBoot统一功能处理前言一、拦截器是什么?二、使用步骤1.定义拦截器2.注册配置拦截器 三,适…...
LibreOffice Writer使用01去除单词拼写判断的红色下划线
这个软件还是非常有特色的,因为大家需要office的全部功能,常常忽略了这个软件的使用体验。 csdn不是特别稳定,linux也没有什么比较好的md编辑器,所以我选择这个软件来记录我的临时博客,原因无他,它可以保存…...
JAVA基础 - 高效管理线程隔离数据结构ThreadLocalMap
欢迎光临小站:致橡树 ThreadLocalMap 是 ThreadLocal 的核心底层数据结构,负责在每个线程中存储与 ThreadLocal 实例绑定的数据。它的设计目标是高效管理线程隔离数据,同时尽量减少内存泄漏风险。以下是其核心实现细节。 数据结构与设计目标…...
每日一题(小白)暴力娱乐篇25
由题意直知,要求将给定的字符串转为符合格式的字符串。首先我们来思考一下例如02/02/02这样的数字日月肯定不用进行修改,修改后需要加上对应的年份的前两位,题目要求1960年1月1日~2059年12年12月31日,(对1960年至2059年…...
地表水-地下水耦合建模全景解析暨SWAT-MODFLOW地表与地下协同模拟及多情景专题应用
第一、模型原理与层次结构 1.1流域水循环与SWAT模型 1.2 地下水模拟与MODFLOW模型 1.3 SWAT-MODFLOW地表-地下耦合模型 1.4 QSWATMOD 插件与功能介绍 1.5 模型实现所需软件平台 第二、QGIS软件 2.1 QGIS平台 2.2 QGIS安装 2.3 QGIS界面认识 2.4 QGIS常见数据格式 2.…...
在线论坛系统
在线论坛 项目介绍项目使用技术介绍前端技术栈后端技术栈 项目运行步骤说明后端运行步骤前端运行步骤 项目使用说明用户端功能管理员端功能 部分功能说明运行截图用户端管理员端 系统源码 项目介绍 这是一个基于现代技术栈开发的在线论坛系统,提供用户交流、内容分享…...
webrtc pacer模块(一) 平滑处理的实现
Pacer起到平滑码率的作用,使发送到网络上的码率稳定。如下的这张创建Pacer的流程图,其中PacerSender就是Pacer,其中PacerSender就是Pacer。这篇文章介绍它的核心子类PacingController及Periodic模式下平滑处理的基本流程。平滑处理流程中还有…...
新能源车「大三电」与「小三电」
一、大三电系统 动力电池 作为整车的能量核心,目前主流类型包括三元锂电池(NCM/NCA)和磷酸铁锂电池(LFP),前者能量密度高,后者安全性和成本优势显著。动力电池通过模组串联形成电池包…...
xlinx GT传输器学习
xlinx有2路refclk会输入到gtbank。此2路bank输入时钟是差分输入,经过IBUFDS_GTE2源语转换为单端。如下图。 从fpga外输入高速差分时钟。 差分时钟转换为单端。 单端时钟输入到gt_common模块 下图为gt内部结构图...
C++笔记之父类引用是否可以访问到子类特有的属性?
C++笔记之父类引用是否可以访问到子类特有的属性? code review! 参考笔记 1.C++笔记之在基类和派生类之间进行类型转换的所有方法 文章目录 C++笔记之父类引用是否可以访问到子类特有的属性?1.主要原因2.示例代码3.说明4.如何访问子类特有的属性5.注意事项6.总结在 C++ 中,…...
基于SSM框架的房屋租赁小程序开发与实现
概述 一个基于SSM框架开发的微信小程序房屋租赁管理系统,该项目实现了用户管理、中介管理、房源信息管理等核心功能。 主要内容 一、管理员模块功能实现 用户管理 管理员可对通过微信小程序注册的用户信息进行修改和删除操作,确保用户数据的准…...
大模型评估论文粗读“AGIEval: A Human-Centric Benchmark for Evaluating Foundation Models“
Zhong W, Cui R, Guo Y, et al. Agieval: A human-centric benchmark for evaluating foundation models[J]. arXiv preprint arXiv:2304.06364, 2023. 摘要翻译 评估大模型在处理人类层级的任务时的通用能力,是AGI发展和应用中至关重要的一环。传统的衡量标准通常依…...
程序化广告行业(76/89):行业融资全景剖析与代码应用拓展
程序化广告行业(76/89):行业融资全景剖析与代码应用拓展 大家好!在之前的文章里,咱们一起了解了程序化广告行业的发展趋势以及PC端和移动端投放的差异。今天,咱们接着深入学习,这次聚焦在程序化…...
网工基础 | 常见英文术语注解
原创:厦门微思网络 以下是一些网工专业常见的英文术语注解: IP Address(Internet Protocol Address) 互联网协议地址,是分配给连接到互联网的设备的唯一标识符,用于在网络中定位和通信。例如,“…...
【FPGA开发技巧】Modelsim仿真中,显示状态机的名称,而非编码数字
示例 被仿真的文件名为:cmd_handle.v,其中有r_st_current和r_st_next两个状态机变量。 该模块在tb文件中,被例化的名称为cmd_handle_u0 按照如下格式写:cmd_handle_u0.r_st_current 示例tb文件: timescale 1ns / 1…...
二分答案----
二分答案 - 题目详情 - HydroOJ 问题描述 给定一个由n个数构成的序列a,你可以进行k次操作,每次操作可以选择一个数字,将其1,问k次操作以后,希望序列里面的最小值最大。问这个值是多少。 输入格式 第一行输入两个正…...
Nginx 命令大全:Linux 与 Windows 系统的全面解析
Nginx 是一个高性能的 HTTP 和反向代理服务器,广泛应用于 Web 服务、负载均衡和反向代理等场景。本文将从 Linux 和 Windows 系统的角度出发,详细解析 Nginx 的常用命令,并区分两种系统之间的差异,帮助你高效地管理和维护 Nginx 服…...
我的计算机网络(总览篇)
总览--网络协议的角度 在一个庞大的网络中,该从哪里去了解呢?我先细细的讲一下我们访问一个网站的全部流程,当我们的电脑连上网络的时候,就会启动DHCP协议,来进行IP地址,MAC地址,DNS地址的分配…...
开源CMS的模块化设计和API接口如何具体影响其扩展性?
优秀的CMS系统都有自己主打的特点,开源CMS凭借其灵活性和低成本优势占据了市场主流地位,而模块化设计与API接口正是其扩展性的两大基石。本文将深入探讨这两大技术特性是如何影响cms的扩展性的。 一、模块化设计:功能解耦与生态繁荣的引擎 …...
【网络原理】网络通信基础
目录 一. 网络发展史 (1)局域网 (2)广域网 二. 网络基础知识 (1)IP地址 (2)端口号 (3)协议 (4)五元组 一. 网络发展史 网络的发…...
Win11系统 VMware虚拟机 安装教程
Win11系统 VMware虚拟机 安装教程 一、介绍 Windows 11是由微软公司(Microsoft)开发的操作系统,应用于计算机和平板电脑等设备 。于2021年6月24日发布 ,2021年10月5日发行 。 Windows 11提供了许多创新功能,增加了新…...
新手宝塔部署thinkphp一步到位
目录 一、下载对应配置 二、加载数据库 三、添加FTP 四、上传项目到宝塔 五、添加站点 六、配置伪静态 七、其他配置 开启监控 八、常见错误 一、打开宝塔页面,下载对应配置。 二、加载数据库 从本地导入数据库文件 三、添加FTP 四、上传项目到宝塔…...
MCU如何查看系统有没有卡死
前言:在我们调试单片机的时候,经常会遇到系统非预期运行的状况。造成系统卡死的原因有很多,主要有:野指针,数组越界,死锁,还有一些while写入的一些逻辑错误。本文就如何排查这些问题,…...