modbus-TCP协议详解
modbus-TCP协议详解
1996年施耐德公司推出基于以太网TCP/IP的modbus协议:modbus-TCP。
MODBUS-TCP使MODBUS-RTU协议运行于以太网,MODBUS-TCP使用TCP/IP以太网在站点间传送MODBUS报文,MODBUS-TCP结合了以太网物理网络和网络标准TCP/IP以及以MODBUS作为应用协议标准的数据表示方法。MODBUS-TCP通信报文包在以太网TCP/IP数据包中。与传统的串口方式,MODBUS-TCP插入一个标准的MODBUS报文到TCP报文中,不再带有数据校验和地址。
MODBUS报文解析
| MBAP Header | Function code | Data |
| Header | PDU |
MBAP header包含下面几个部分:
- Transaction ID
- Protocol ID
- Length
- UnitID
id | 名称 | 长度 | 说明 |
---|---|---|---|
1 | Transaction ID 事务处理标识 | 2字节 | 报文的序列号,一般每次通讯加1,用于区别不同的报文 |
2 | Protocol ID 协议标识 | 2字节 | 00 00 代表modbus-Tcp |
3 | Length | 2字节 | Unit长度 + PDU的长度 |
4 | UnitID | 单元标识符 | 1 |
下面的这一串MBAP header|00 01| 00 00|00 06| 01 |, 其含义如下:
事务标识为1,协议是modbus-tcp协议,数据长度是:6,从站号是1。
需要注意的是MODBUS协议是一个大端的协议,前两个byte 00 01代表0x1 , 因此Transaction ID=1。而长度字段00 06代表0x6, 即UnitID和PDU的长度总和为6。
PDU部分相对复杂一些,主要是对一些寄存器进行读写操作。
modbus的操作对象有四种:线圈寄存器、离散输入寄存器、输入寄存器、保持寄存器。
寄存器种类 | 数据类型 | 访问类型 | 功能码 |
---|---|---|---|
线圈寄存器 | bit | 读写 | 01H 05H 0FH |
离散输入寄存器 | bit | 只读 | 02H |
输入寄存器 | 2 bytes(word) | 只读 | 04H |
保持寄存器 | 2 bytes(word) | 读写 | 03H 06H 10H |
线圈寄存器和离散输入寄存器是以bit为单位的寄存器,只能存储开关量,线圈寄存器可读可写,而离散输入寄存器只可读。
输入寄存器和保持寄存器以为2个byte为单位的寄存器,可以存储离散的变量, 保持寄存器可读可写, 输入寄存器只读。
常用的功能码作用如下:
功能码 | 功能 |
---|---|
0x01 | 读单个或者多个线圈寄存器 |
0x02 | 读离散量输入寄存器 |
0x03 | 读保持寄存器 |
0x04 | 读输入寄存器 |
0x05 | 写单个线圈寄存器 |
0x06 | 写单个保持寄存器 |
0x10 | 写多个保持寄存器 |
0x0F | 写多个线圈寄存器 |
常用功能码详解
功能码0x1:读线圈寄存器
每个线圈寄存器可以存储一个bit的信息, 功能码0x01就是用于读取slave中线圈寄存器的状态,可以是单个线圈寄存器,也可以是多个连续的线圈寄存器。
发送报文
发送报文由下面几个部分组成,总共12字节:
MBAP header(7字节) + 功能码(1字节) + 线圈寄存器起始地址的高位(1字节) + 线圈寄存器起始地址的低位(1字节) + 线圈寄存器数量的高位(1字节) + 线圈寄存器数量的低位(1字节)
下面是一个用Modbus-Poll和Modbus-Slave测试的实际的例子,其含义是读取线圈寄存器的起始地址是0x0, 读取数量为 0x0a(十进制10)个。
MBAP header | 功能码 | 起始地址高字节 | 起始地址低字节 | 寄存器数量的高位 | 寄存器数量的低位 |
---|---|---|---|---|---|
01 66 00 00 00 06 01 | 01 | 00 | 00 | 00 | 0a |
其中:
TransanctionID = 358, Length = 6。
功能码为0x1,代表读取线圈寄存器。
读取的线圈寄存器的起始地址为0。
读取的线圈寄存器的数量为0xa(十进制10)个。
响应报文
响应报文的长度不是固定的,长度和用户请求的数据长度有关,由下面几个部分组成:
MBAP header(7字节) + 功能码(1字节) + 线圈寄存器的值
下面是一个实际的响应报文的内容:
MBAP header | 功能码 | 字节数 | 请求的数据1 | 请求的数据2 |
---|---|---|---|---|
01 66 00 00 00 05 01 | 01 | 02 | 21 | 02 |
返回的第一个字节21,转化为二进制为00100001, 其中bit0代表00寄存器,bit7代表07寄存器。
0x7 | 0x6 | 0x5 | 0x4 | 0x3 | 0x2 | 0x1 | 0x0 |
---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
返回的第二个字节02,转化为二进制为00000010, 其中bit0代表08寄存器,bit1代表09寄存器。
0x9 | 0x8 |
---|---|
1 | 0 |
功能码0x5: 写单个线圈寄存器0x05:
功能码0x5的作用是对单个线圈寄存器写值ON/OFF。
发送报文
发送报文由下面几个部分组成,总共12字节:
MBAP header(7字节) + 功能码(1字节) + 线圈寄存器起始地址的高位(1字节) + 线圈寄存器起始地址的低位(1字节) + 要写的值的高位(1字节) + 要写的值的低位(1字节)
将从站中的一个输出写成ON或OFF,0xFF00代表为ON,0x0000代表为OFF。
下面是一个实际的例子:
MBAP header | 功能码 | 起始地址高字节 | 起始地址低字节 | 写的值的高位 | 写的值的低位 |
---|---|---|---|---|---|
00 6f 00 00 00 06 01 | 05 | 00 | 04 | ff | 00 |
在这个例子中,对从站01的0x4号线圈执行ON操作。
响应报文
可以看到,如果写单个线圈成功,返回报文的值和发送报文的值相同:
功能码0x0F:写多个线圈寄存器
将一个从站中的多个线圈寄存器的写为ON或OFF,数据域中置1的位请求相应输出位ON,置0的位请求响应输出为OFF。
发送报文
发送报文由下面几部分组成:
MBAP 功能码 + 起始地址H 起始地址L + 输出数量H 输出数量L + 字节长度 + 输出值H 输出值L
其总长度为 13 + (修改的线圈寄存器数量/8 + 1)。
下面是一个实际的例子
按照协议进行对应的结果如下:
MBAP header | 功能码 | 线圈寄存器起始位置 | 线圈寄存器的数量 | 字节数 | 第一个byte的值 | 第二个byte的值 |
---|---|---|---|---|---|---|
01 71 00 00 00 09 01 | 0f | 00 00 | 00 0a | 02 | 70 | 00 |
其中第一个byte的值是0x70, 转换为二进制是01110000,其中低位bit0代表00寄存器,bit7代表07寄存器。
0x7 | 0x6 | 0x5 | 0x4 | 0x3 | 0x2 | 0x1 | 0x0 |
---|---|---|---|---|---|---|---|
0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
第二个byte的值是0x0, 转换为二进制是00000000,其中低位bit0代表08寄存器,bit1代表09寄存器。
0x9 | 0x8 |
---|---|
0 | 0 |
该请求的作用起始就是将04 05 06寄存器的状态改为ON。
返回报文
返回的报文相对比较简单,由下面几个部分组成:
MBAP header + 功能码 + 起始地址H 起始地址L + 输出数量H 输出数量L
下面是一个实际的例子:
按照协议对应各部分的内容如下:
MBAP header | 功能码 | 线圈寄存器起始位置 | 线圈寄存器的数量 |
---|---|---|---|
01 71 00 00 00 06 01 | 0f | 00 00 | 00 0a |
功能码0x02:读离散量输入寄存器
功能码0x2和0x1是比较类似的。只是操作的离散量输入寄存器是只读的,没有写操作的接口。
每个离散量输入寄存器可以存储一个bit的信息, 功能码0x02就是用于读取slave中离散量输入寄存器的状态,可以是单个线圈寄存器,也可以是多个连续的线圈寄存器。
发送报文
发送报文由下面几个部分组成,总共12字节:
MBAP header(7字节) + 功能码(1字节) + 离散量输入寄存器起始地址的高位(1字节) + 离散量输入寄存器起始地址的低位(1字节) + 离散量输入寄存器数量的高位(1字节) + 离散量输入寄存器数量的低位(1字节)
下面是一个用Modbus-Poll和Modbus-Slave测试的实际的例子,其含义是读取线圈寄存器的起始地址是0x0, 读取数量为 0x0a(十进制10)个。
MBAP header | 功能码 | 起始地址高字节 | 起始地址低字节 | 寄存器数量的高位 | 寄存器数量的低位 |
---|---|---|---|---|---|
01 b9 00 00 00 06 01 | 01 | 00 | 00 | 00 | 0a |
其中:
TransanctionID = 441, Length = 6。
功能码为0x1,代表读取线圈寄存器。
读取的线圈寄存器的起始地址为0。
读取的线圈寄存器的数量为0xa(十进制10)个。
响应报文
响应报文的长度不是固定的,长度和用户请求的数据长度有关,由下面几个部分组成:
MBAP header(7字节) + 功能码(1字节) + 离散量输入寄存器的值
下面是一个实际的响应报文的内容:
MBAP header | 功能码 | 字节数 | 请求的数据1 | 请求的数据2 |
---|---|---|---|---|
01 b9 00 00 00 05 01 | 01 | 02 | 12 | 02 |
返回的第一个字节12,转化为二进制为00010010, 其中bit0代表00寄存器,bit7代表07寄存器。
0x7 | 0x6 | 0x5 | 0x4 | 0x3 | 0x2 | 0x1 | 0x0 |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
返回的第二个字节02,转化为二进制为00000010, 其中bit0代表08寄存器,bit1代表09寄存器。
0x9 | 0x8 |
---|---|
1 | 0 |
功能码0x03:读保持寄存器
功能码0x03用于读取保持寄存器的值,从远程设备中读保持寄存器连续块的内容。
发送报文
请求报文的结构如下:
MBAP header + 功能码 + 起始地址H 起始地址L + 寄存器数量H 寄存器数量L(共12字节)
下面是一个实际的例子:
按照协议对照如下:
MBAP header | 功能码 | 起始地址 | 寄存器数量 |
---|---|---|---|
05 f1 00 00 00 06 01 | 03 | 00 00 | 00 0a |
响应报文
响应报文的结构由下面几个部分组成:
MBAP header + 功能码 + 数据长度 + 寄存器数据
数据总长度 = 9 + 寄存器数量 × 2
下面是一个response的结构:
从中我们可以提取出下面的对应关系:
MBAP header | 功能码 | 字节数 | 第0byte值 | 第1byte值 | 第2byte值 | 第3byte值 | 第4byte值 | 第5byte值 | 第6byte值 | 第7byte值 | 第8byte值 | 第9byte值 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
05 f1 00 00 00 17 01 | 03 | 14 | 01 2c | 00 00 | 00 00 | 00 37 | 00 00 | 00 00 | 00 64 | 00 00 | 00 3c | 00 00 |
由上面的对应关系,我们可以提取出我们想要读取的保持寄存器的值:
第0个寄存器 | 第1个寄存器 | 第2个寄存器 | 第3个寄存器 | 第4个寄存器 | 第5个寄存器 | 第6个寄存器 | 第7个寄存器 | 第8个寄存器 | 第9个寄存器 |
---|---|---|---|---|---|---|---|---|---|
300 | 0 | 0 | 55 | 0 | 0 | 100 | 0 | 60 | 0 |
功能码0x04:读输入寄存器
功能码0x4用于读取输入寄存器的值,输入寄存器是只读的,因此没有功能码可以写输入寄存器。
发送报文
请求报文格式如下:
MBAP header + 功能码 + 起始地址H 起始地址L + 寄存器数量H 寄存器数量L(共12字节)
下面是一个实际的例子:
MBAP header | 功能码 | 起始地址 | 寄存器数量 |
---|---|---|---|
0b f8 00 00 00 06 01 | 04 | 00 00 | 00 0a |
该请求的含义是读取0-9号寄存器的值。
响应报文
响应报文的结构由下面几个部分组成:
MBAP header + 功能码 + 数据长度 + 寄存器数据
数据总长度 = 9 + 寄存器数量 × 2
下面是一个response的结构:
从中我们可以提取出下面的对应关系:
MBAP header | 功能码 | 字节数 | 第0byte值 | 第1byte值 | 第2byte值 | 第3byte值 | 第4byte值 | 第5byte值 | 第6byte值 | 第7byte值 | 第8byte值 | 第9byte值 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0b f8 00 00 00 17 01 | 04 | 14 | 00 00 | 00 00 | 00 c8 | 00 00 | 01 2c | 00 00 | 00 00 | 00 00 | 00 42 | 00 00 |
由上面的对应关系,我们可以提取出我们想要读取的保持寄存器的值:
第0个寄存器 | 第1个寄存器 | 第2个寄存器 | 第3个寄存器 | 第4个寄存器 | 第5个寄存器 | 第6个寄存器 | 第7个寄存器 | 第8个寄存器 | 第9个寄存器 |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 200 | 0 | 300 | 0 | 0 | 0 | 66 | 0 |
功能码0x06:写单个保持寄存器
在一个远程设备中写一个保持寄存器。
发送报文
请求报文格式如下:
MBAP header + 功能码 + 寄存器地址H 寄存器地址L + 寄存器值H 寄存器值L(共12字节)
下面是一个实际的例子:
MBAP header | 功能码 | 保持寄存器地址 | 保持寄存器的值 |
---|---|---|---|
1F 97 00 00 00 06 01 | 06 | 00 04 | 00 64 |
该请求的含义是向地址为0x4的寄存器写入100。
响应报文
响应报文如下:
MBAP header + 功能码 + 寄存器地址H 寄存器地址L + 寄存器值H 寄存器值L(共12字节)
成功响应的报文与发送报文格式相同。
功能码0x10:写多个保持寄存器
在一个远程设备中写连续寄存器块(1~123个寄存器)
发送报文
请求报文格式如下:
MBAP header + 功能码 + 起始地址H 起始地址L + 寄存器数量H 寄存器数量L + 字节长度 + 寄存器值(13+寄存器数量×2)
MBAP header | 功能码 | 起始地址 | 长度 | 字节数 | 字节0数据 | 字节1数据 | 字节2数据 | 字节3数据 | 字节4数据 | 字节5数据 | 字节6数据 | 字节7数据 | 字节8数据 | 字节9数据 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00 26 00 00 00 1b 01 | 10 | 00 00 | 00 0a | 14 00 | 00 00 | 00 00 | 00 00 | 00 00 | 00 c8 | 00 00 | 00 00 | 00 64 | 00 00 | 00 64 |
响应报文
响应报文如下:
MBAP header + 功能码 + 起始地址H 起始地址L + 寄存器数量H 寄存器数量L(共12字节)
MBAP header | 功能码 | 起始地址 | 长度 |
---|---|---|---|
00 26 00 00 00 1b 01 | 10 | 00 00 | 00 0a |
实用调试工具
在研究modbus的过程中, 大量的使用了modbus poll和 modbus slave软件,这个软件可以很好的帮助理解modbus-tcp协议。
modbus poll: modbus客户端工具(主站)
modbus slave: modbus服务端工具(从站)
相关文章:

modbus-TCP协议详解
modbus-TCP协议详解 1996年施耐德公司推出基于以太网TCP/IP的modbus协议:modbus-TCP。 MODBUS-TCP使MODBUS-RTU协议运行于以太网,MODBUS-TCP使用TCP/IP以太网在站点间传送MODBUS报文,MODBUS-TCP结合了以太网物理网络和网络标准TCP/IP以及以…...

爬虫项目(12):正则、多线程抓取腾讯动漫,Flask展示数据
文章目录 书籍推荐正则抓取腾讯动漫数据Flask展示数据 书籍推荐 如果你对Python网络爬虫感兴趣,强烈推荐你阅读《Python网络爬虫入门到实战》。这本书详细介绍了Python网络爬虫的基础知识和高级技巧,是每位爬虫开发者的必读之作。详细介绍见ὄ…...
gedit编辑文件时常用快捷键
问题: 最近在修改文件时提到了gedit这个工具,与vi一样也是一个文件编辑器。但是在命令方面又有不同,在快捷键方面和Windows的使用习惯非常相似。 gedit举例: CTRL-Z:撤销CTRL-C:复制CTRL-V:粘贴CTRL-T:缩进CTRL-Q:退出CTRL-S:保…...
【C++干货铺】剖析string | 底层实现
个人主页点击直达:小白不是程序媛 C专栏:C干货铺 代码仓库:Gitee 目录 成员变量 成员函数 构造和拷贝构造 赋值重载 析构函数 operator[ ] size 迭代器 reserve(扩容函数) push_back(尾插函数)…...

nmap原理与使用
kali的命令行中可以直接使用 nmap 命令,打开一个「终端」,输入 nmap 后回车,可以看到 nmap 的版本,证明 nmap 可用。 一、端口扫描 扫描主机的「开放端口」,在nmap后面直接跟主机IP(默认扫描1000个端口&am…...

AI批量剪辑矩阵托管系统----源码技术开发
AI批量剪辑矩阵托管系统----源码技术开发 抖音账号矩阵系统是基于抖音开放平台研发的用于管理和运营多个抖音账号的平台。它可以帮助用户管理账号、发布内容、营销推广、分析数据等多项任务,从而提高账号的曝光度和影响力。 具体来说,抖音账号矩阵系统可…...
Pandas数据预处理python 数据分析之4——pandas 预处理在线闯关_头歌实践教学平台
Pandas数据预处理python 数据分析之4——pandas 预处理 第1关 数据读取与合并第2关 数据清洗第3关 数据转换 第1关 数据读取与合并 任务描述 本关任务:加载 csv 数据集,实现 DataFrame 合并。 编程要求 根据提示,在右侧编辑器补充代码&#…...

[html] 动态炫彩渐变背景
废话不多说,直接上源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>ZXW-NUDT: 动态炫…...

AI 绘画 | Stable Diffusion 高清修复、细节优化
前言 在 Stable Diffusion 想要生成高清分辨率的图片。在文生图的功能里,需要设置更大的宽度和高度。在图生图的功能里,需要设置更大的重绘尺寸或者重绘尺寸。但是设置完更大的图像分辨率,需要更大显存,1024*1024的至少要电脑的空…...

想要检测TikTok网络是否安全?这五个网站请收好
Tiktok目前在海外大火,越来越多的人想要进入TikTok的海外市场并捞一桶金。然而,成功并非易事。想要在TikTok中立足,我们必须保证我们的设备、网络环境和网络节点完全符合官方的要求,并且没有任何异常或风险。那么我们该如何设置、…...

【docker:容器提交成镜像】
容器创建部分请看:点击此处查看我的另一篇文章 容器提交为镜像 docker commit -a "sinwa lee" -m "首页变化" mynginx lxhnginx:1.0docker run -d -p 88:80 --name lxhnginx lxhnginx:1.0为啥没有变啊,首页? 镜像打包 …...
UE5中一机一码功能
创建蓝图函数库 1、获取第一个有效的硬盘ID // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "GetDiskIDClass.gen…...

gpt支持json格式的数据返回(response_format: ‘json_object‘)
Api.h5.chatCreateChatCompletion({model: gpt-3.5-turbo-1106,token: sk-f4fe8b67-fcbe-46fd-8cc9-fd1dac5d6d59,messages: [{role: user,content:使用json格式返回十二生肖,包含中文名和英文名,[{id:"1", enName:"", cnName: &quo…...
MySQL(13):约束
约束(constraint)概述 数据完整性(Data Integrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。 它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息 而提…...

可以为一个servlet定义多个servlet-mapping、或url-pattern
在web描述符文件web.xml文件中,可以为同一个servlet定义多个servlet-mapping;也可以在同一个servlet-mapping中,定义多个url-pattern。也就是说,可以把多个地址(相对于上下文路径)映射到同一个servlet处理。…...

.net在使用存储过程中IN参数的拼接方案,使用Join()方法
有时候拼接SQL语句时,可能会需要将list中的元素都加上单引号,并以逗号分开,但是Join只能简单的分开,没有有单引号! 1.第一种拼接方案 List<string> arrIds new List<string>(); arrIds.Add("aa&qu…...

基于RK3399的室内健身魔镜方案
I 方案背景 一、健身魔镜的兴起 2020年疫情席卷全球,宅家是防疫的措施之一,因而宅家运动火爆,随之而来的宅家运动器材也风靡起来,其中包含既有颜值又具有多种功能的健身魔镜。 Ⅱ 方案介绍 一、健身魔镜的方案介绍 …...

leetCode 25.K 个一组翻转链表
给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。k 是一个正整数,它的值小于 或 等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。你不能只是单纯的改变节点内部的值&a…...

ElasticSearch中常见的分词器介绍
文章目录 ElasticSearch中常见的分词器介绍前言分词器的作用如何指定分词器分词器的组成分词器的类型标准分词器空格分词器简单分词器关键词分词器停用词分词器IK分词器NGram分词器正则匹配分词器语言分词器自定义分词器 ElasticSearch中常见的分词器介绍 前言 ElasticSearch是…...

前端案例-css实现ul中对li进行换行
场景描述: 我想要实现,在展示的item个数少于4个的时候,则排成一行,并且均分(比如说有3个,则每个的宽度为33.3%),如果item 个数大于4,则进行换行。 效果如下:…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...