IO Virtualization with Virtio.part 1 [十二]
久等了各位!
本篇开始讲解 IO 虚拟化中的 virtio,我会以 Linux 的 IIC 驱动为例,从 IIC 驱动的非虚拟化实现,到 IIC 驱动的半虚拟化实现,再到最后 X-Hyper 中如何通过 virtio 来实现前后端联系,一步步把 virtio 讲清楚。所以我一共会分为4个子篇幅来介绍virtio,内容有点多,需要一点点消化。
本篇我们以 RK 板的 IIC 控制器为例,先讲解 Linux 下的 IIC 驱动框架。
设备树创建 i2c 设备的节点,在设备树遍历时会创建一个 i2c 的 platform 设备出来:
i2c@fdd40000 {compatible = "rockchip,rk3399-i2c";reg = <0x00 0xfdd40000 0x00 0x1000>;clocks = <0x32 0x07 0x32 0x2d>;clock-names = "i2c\0pclk";interrupts = <0x00 0x2e 0x04>;pinctrl-names = "default";pinctrl-0 = <0x35>;#address-cells = <0x01>;#size-cells = <0x00>;status = "okay";phandle = <0x17a>;}
设备包含如下信息:
- compatible:兼容性,用于匹配可以用于该设备的驱动;
- reg:该设备的寄存器基地址和范围;
- interrupts:i2c 中断控制器使用的中断配置;
这个 platform device 在被放入平台总线时,会匹配对应的 platform driver,那么先来看一下 platform bus 是什么:
struct bus_type platform_bus_type = {.name = "platform",.dev_groups = platform_dev_groups,.match = platform_match,.uevent = platform_uevent,.dma_configure = platform_dma_configure,.pm = &platform_dev_pm_ops,
};
我们只关注其中的 match 函数,它是当一个新的设备或者一个新的驱动被添加到该总线时会被调用的匹配函数,当一个新的设备被加入时,使用 match 来匹配对应的驱动,当一个新的驱动被添加到该总线时,也会使用这个 match 来匹配设备。
我们以 rk 板的 i2c 平台总线驱动为例,首先我们找到 rk 板的 i2c 平台总线驱动:
static struct platform_driver rk3x_i2c_driver = {.probe = rk3x_i2c_probe,.remove = rk3x_i2c_remove,.driver = {.name = "rk3x-i2c",.of_match_table = rk3x_i2c_match,.pm = &rk3x_i2c_pm_ops,},
};
使用of_match_table 来匹配对应的的设备,使用probe 来初始化设备。
整体流程如下:
在深入分析 IIC 的驱动代码前,先简单看一下 IIC 的整个数据发送和接受流程,这里不会涉及底层硬件的时序,需要读者自己去学习。
IIC 主机向从机写数据:
IIC 主机向从机读数据:
当然IIC的发送接收不止上述两种模式,这里只讨论常用的两种发送和接收数据的方法。
然后我们开始分析 IIC platform driver 的代码了:
我们以 RK board 为例,其总线驱动代码在:drivers\i2c\busses\i2c-rk3x.c 中,具体实现可以参考我之前的文章,这里只给出一个整体框图。最终 i2c 的控制器也会以字符设备节点暴露给用户态,我们可以通过 i2c 控制器的字符设备给相应的 i2c 外设通信。
然后看一下用户层打开一个 i2c 控制器对应的字符设备节点的整体流程图:
整个流程如下:
当应用程序打开一个设备文件时,通过系统调用 sys_open 进入内核,在内核空间中由 do_sys_open 负责发起整个设备文件的打开操作,首先获得该设备文件所对应的 inode,然后调用其中的 i_fop 函数,对字符设备而言,i_fop 函数就是 chrdev_open,后者通过 inode 中的 i_rdev 成员在 cdev_map 中查找该设备所对应的设备对象 cdev,在成功找到了该设备对象后,将 inode 的 cdev 成员指向该字符设备对象,这样下次再对该设备文件节点进行打开操作时,就可以直接通过 i_cdev 成员得到设备节点所对应的字符设备对象了。内核在每次打开一个设备文件时,会产生一个整形的文件描述符 fd 和一个新的 struct file 对象 filp 来跟踪对该文件的这一次操作,在打开设备文件时,内核会将 filp 和 fd 关联起来,同时会将 cdev 中的 ops 赋值给 filp->f_op,同时创建 i2c_client,关联 i2c_adapter,并将 filp 的 private_data 和 i2_client 关联起来。最后 sys_open 系统调用将设备文件描述符 fd 返回到用户空间。
接下来用一个实际的例子去理解一下 IIC 的完成一次 Combined R/W 的流程:
用户侧示例代码如下:
int main(void)
{int fd = 0;int ret = 0;const char *path_name ="/dev/i2c-0";uint8_t buf[8] = {0};uint8_t start_reg = 0x0;struct i2c_msg read_msg[2] = {{0x20, /* slave addr */0, /* operate flags */1, /* data len */&start_reg /* data buf */},{0x20, /* slave addr */I2C_M_RD, /* operate flags */8, /* data len */&buf[0] /* data buf */},};struct i2c_rdwr_ioctl_data rdwr = {.msgs = read_msg,.nmsgs = 2};fd = open(path_name, O_RDWR);ret = ioctl(fd, I2C_SLAVE_FORCE, 0x20);ret = ioctl(fd, I2C_RDWR, (unsigned long)&rdwr);return 0;
}
这是一次 Combined 的从机数据读取操作,由两部分i2c_msg 组成,第一个 msg 向从机写设备寄存器地址,表示要读取的设备寄存器,然后再发送读数据请求,向从机请求 8 个字节的 data。
对应整个 IIC 的协议段如下:
然后我们通过 ioctl 进入内核,并最终调用 i2cdev_fops->i2cdev_ioctl。
static const struct file_operations i2cdev_fops = {....compat_ioctl = compat_i2cdev_ioctl,...
};static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{struct i2c_client *client = file->private_data;...switch (cmd) {...case I2C_RDWR: {...return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);}...return 0;
}static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,unsigned nmsgs, struct i2c_msg *msgs)
{...res = i2c_transfer(client->adapter, msgs, nmsgs);...return res;
}int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{...ret = __i2c_transfer(adap, msgs, num);return ret;
}int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{...ret = adap->algo->master_xfer(adap, msgs, num);...return ret;
}
可以看到最后就是调用了i2c_adapter 中的master_xfer。
static int rk3x_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msgs, int num)
{struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data;...for (i = 0; i < num; i += ret) {ret = rk3x_i2c_setup(i2c, msgs + i, num - i);...rk3x_i2c_start(i2c);...}...
}
rk3x_i2c_xfer 中初始化MRXADDR 和 MRXRADDR 寄存器并初始化 i2c 的初始化状态机状态。然后通过rk3x_i2c_start 发送 start 信号开始 i2c 的整个流程,并在rk3x_i2c_irq 中维护整个 i2c 数据发送和接受的状态机:
static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id)
{...switch (i2c->state) {case STATE_START:rk3x_i2c_handle_start(i2c, ipd);break;case STATE_WRITE:rk3x_i2c_handle_write(i2c, ipd);break;case STATE_READ:rk3x_i2c_handle_read(i2c, ipd);break;case STATE_STOP:rk3x_i2c_handle_stop(i2c, ipd);break;case STATE_IDLE:break;}...
}
在 Combined W/R 模式下的流程图和状态机如下所示:
流程图:
IIC 驱动状态机:
到这里我们简单的介绍了Linux下的IIC驱动框架和其工作流程,如果要深入理解还需自己阅读驱动代码,下一篇幅将介绍IIC半虚拟化的Virtio前端驱动。
相关文章:
IO Virtualization with Virtio.part 1 [十二]
久等了各位! 本篇开始讲解 IO 虚拟化中的 virtio,我会以 Linux 的 IIC 驱动为例,从 IIC 驱动的非虚拟化实现,到 IIC 驱动的半虚拟化实现,再到最后 X-Hyper 中如何通过 virtio 来实现前后端联系,一步步把 v…...
单元测试4.0+思路总结
Jmockit使用笔记_增加代码覆盖率_覆盖try catch_使用new MockUp私有方法-CSDN博客 一般使用new MockUp模拟被测试代码中的私有方法(常用) 使用new Expetations模拟被测试代码中的方法?...
微信小程序中遇到过的问题
记录微信小程序中遇到的问题(持续更新ing) 问题描述:1. WXML中无法直接调用JavaScript方法。2. css中无法直接引用背景图片。3. 关于右上角胶囊按钮。4. 数据绑定问题。5. 事件处理问题。6. 关于movable-view组件的问题7. 关于设置宽度后设置…...
气象数据Grib及Python绘图
文章较长,却将所有常见的气象数据类型进行了详细的介绍,对各种方法的优劣势进行了详细分析,相信对于阅读者来说会有一定程度的帮助 目录 GRIB 数据格式简介 使用Python处理Grib文件 法1:使用pygrib库 法2:使用cf…...
Vue el-data-picker选中开始时间,结束时间自动加半小时
效果 思路 查阅elemnet plus官网,日期时间选择器type"datetimerange"这个选中开始时间并没有对应事件会被触发,因此思路更换成type"datetime"的两个组成一起可以通过监听开始时间v-model的值变化更新结束时间的值。 代码 日期时间…...
mac下载Homebrew安装nvm
通过Homebrew安装 - 国内下载地址 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"安装nvm brew install nvm 配置nvm环境变量 export NVM_DIR“$HOME/.nvm” [ -s “/usr/local/opt/nvm/nvm.sh” ] && . “/usr/…...
模型并行、数据并行、流水线并行以及混合并行的适用场景、优劣
模型并行、数据并行、流水线并行以及混合并行的适用场景、优劣 数据并行 适用场景:适用于模型规模相对较小,能够在单个计算设备(如 GPU)上完整运行,但训练数据量巨大的情况。例如在大规模图像分类任务中,常见的卷积神经网络模型(如 ResNet、VGG 等)在处理大规模图像数据…...
【容器化技术 Docker 与微服务部署】详解
容器化技术 Docker 与微服务部署 一、容器化技术概述 (一)概念 容器化技术是一种操作系统级别的虚拟化方法,它允许将应用程序及其依赖项(如运行时环境、系统工具、库等)打包成一个独立的、可移植的单元,这…...
MySQL——数据类型
一、常见的数据类型及分类 其中上述的数值类型包含了整形和浮点型,文本、二进制类型主要是字符串类型。 整数类型(Integer Types): TINYINT:范围为-128到127或0到255(无符号),用于…...
基于傅立叶神经网络(FNN)与物理信息神经网络(PINN)求解泊松方程(附Pytorch源代码)
基于傅立叶神经网络(FNN)与物理信息神经网络(PINN)求解泊松方程 一、引言 偏微分方程(Partial Differential Equation, PDE)在科学与工程领域有着广泛的应用。传统数值方法(如有限差分法、有限元法)在求解这类问题时,尽管已经非常成熟,但随着问题复杂度的增加,其计…...
FastExcel:超越EasyExcel的新一代Excel处理工具
简介 FastExcel是由原EasyExcel作者在阿里巴巴宣布停止维护EasyExcel之后推出的升级版框架。它继承了EasyExcel的所有优点,并且在性能和功能上进行了显著的提升和创新。 FastExcel的特点 高性能读写:FastExcel专注于性能优化,能够高效处理…...
项目优化性能监控
目录 1. 性能平台搭建 1.1 影响性能的关键要素 1.2 压力测试 1.3 压力测试指标 1.4 Jmeter 1.5 Jmeter常用插件 1.6 性能关键指标 1.7 服务器硬件资源监控 1.8 系统负载:load average 1.9 搭建压测监控平台 1.10 梯度压测:分析接口性能瓶颈 2. 项目优化…...
linux装git
前言 以 deepin 深度系统为例,安装命 令行版 Git 非常简单。 安装 注意:需要输入账号密码,否则无法进行。 打开终端,执行如下命令即可。 sudo apt-get install git成功 如下图所示,输入 git ,命令识别即…...
2024 年度总结
时光荏苒,2024 年即将画上句号,回顾这一年的写博历程,有付出、有收获、有成长,也有诸多值得回味与反思的瞬间。 一、内容创作 主题涉猎:这一年,我致力于探索多样化的主题,以满足不同读者群体的…...
实验八 指针2
7-1 利用指针返回多个函数值 分数 30 全屏浏览 切换布局 作者 陈晓梅 单位 广东外语外贸大学 读入n个整数,调用max_min()函数求这n个数中的最大值和最小值。 输入格式: 输入有两行: 第一行是n值; 第二行是n个数。 输出格式: 输出最大…...
python修改ppt中的文字部分及插入图片
批量修改ppt中的某个模块,或者批量制作奖状等场景会用到; import os import pandas as pd from pptx import Presentation from pptx.util import Inchesfilepath/Users/kangyongqing/Documents/kangyq/202303/分析模版/批量制作/file1时段预警_副本.pp…...
C进阶-字符串与内存函数介绍(另加2道典型面试题)
满意的话,记得一键三连哦! 我们先看2道面试题 第一道: 我们画图理解: pa,先使用再,pa开始指向a【0】,之后pa向下移动一位,再解引用,指向a【1】,a【1】又指向…...
Github - 如何提交一个带有“verified”标识的commit
Github - 如何提交一个带有“verified”标识的commit 前言(Why) 今天在Github上浏览某项目的commit记录的时候发现,有的commit记录带有verified绿色标识,有的带有橘色的Unverified标识,还有的什么都不显示。 既然我是根正苗红的作者(bushi)…...
充电桩语音提示IC方案-支持OTA远程更换语音WT2003H让充电更智能
随着新能源汽车产业的蓬勃发展,充电桩作为电动汽车能量补给的关键设施,其智能化、人性化设计日益成为行业关注的焦点。在这一背景下,WT2003H4-16S语音芯片方案的推出,无疑为充电桩的智能化升级注入了新的活力。该方案不仅提升了充…...
[2474].第04节:Activiti官方画流程图方式
我的后端学习大纲 Activiti大纲 1.安装位置: 2.启动:...
开源的Vue低代码表单设计器 form-create-designer v3.2.9 版本发布,新增10多种功能
form-create-designer 是一款开源的低代码表单设计器,通过数据驱动表单渲染。可以通过拖拽的方式快速创建表单,提高开发者对表单的开发效率,节省开发者的时间。并广泛应用于在政务系统、OA系统、ERP系统、电商系统、流程管理等领域。 项目采…...
0042__【小沐学OpenGL】Ubuntu环境下glfw的安装和使用
【小沐学OpenGL】Ubuntu环境下glfw的安装和使用_ubuntu glfw-CSDN博客 OpenGL 打开绘制窗口 学习笔记_glfwmakecontextcurrent-CSDN博客...
第一节:电路连接【51单片机+A4988+步进电机教程】
摘要:本节介绍如何搭建一个51单片机A4988步进电机控制电路,所用材料均为常见的模块,简单高效的方式搭建起硬件环境 一、硬件清单 ①51单片机最小控制模块 ②开关电源 ③A4988模块转接座 ④二相四线步进电机 ⑤电线若干 二、接线 三、A49…...
k8s 部署meilisearch UI
https://github.com/riccox/meilisearch-ui 拉取镜像 sudo docker pull riccoxie/meilisearch-ui:latestk8s 部署 apiVersion: v1 kind: Service metadata:name: meilisearch-uinamespace: meilisearch spec:type: NodePortselector:app: meilisearch-uiports:- port: 24900…...
在基于Centos7的服务器上启用【Gateway】的【Clion Nova】(即 ReSharper C++ 引擎)
1. 检查启动报错日志,目录在 ~/.cache/JetBrains/CLion202x.x.x/log/backend.202x-xx-xx_xxxx.xxxx-err.log 2. 大致可能有两种报错 a. Process terminated. Couldnt find a valid ICU package installed on the system. 这个报错只需要装一下 libicu-devel 包即可…...
【Rust自学】7.4. use关键字 Pt.1:use的使用与as关键字
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 7.4.1. use的作用 use的作用是将路径导入到当前作用域内。而引入的内容仍然是遵守私有性原则,也就是只有公共的部分引入进来才…...
HTML5实现喜庆的新年快乐网页源码
HTML5实现喜庆的新年快乐网页源码 前言一、设计来源1.1 主界面1.2 关于新年界面1.3 新年庆祝活动界面1.4 新年活动组织界面1.5 新年祝福订阅界面1.6 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现喜庆的新年快乐网页源码,春节新年网…...
C++新特性||线程协程(代码解析1)
原文https://blog.csdn.net/ke_wu/article/details/144807820?sharetypeblogdetail&sharerId144807820&sharereferPC&sharesourceke_wu&spm1011.2480.3001.8118 #ifndef ZERO_THREADPOOL_H #define ZERO_THREADPOOL_H#include <future> // 用于…...
《成瘾-在放纵中寻找平衡》
安娜伦布克(Anna Lembke)是美国著名的精神病学家、成瘾医学专家以及《多巴胺国度》(Dopamine Nation)的作者。她在书中深入探讨了现代社会中的成瘾问题,并结合科学研究与临床经验,揭示了为什么现代人更容易…...
Docker搭建Skywalking
Docker搭建Skywalking 虚拟机IP:192.168.0.109Nacos服务地址:http://192.168.0.109:8848/nacosMySQL服务: IP:192.168.0.109端口:3306用户名:root密码:root ElasticSearch服务: IP&a…...
Vue axios 异步请求,请求响应拦截器
在 Vue.js 中使用 axios 进行网络请求是非常常见的做法,因为它提供了比原生的 Fetch API 更丰富的功能,并且更易于处理错误和配置。结合 Axios 的拦截器功能,你可以对所有的请求或响应进行预处理,比如添加认证头信息、统一处理错误…...
解决 ffmpeg “Unknown encoder ‘hevc_nvenc‘“
目录 项目场景: 问题描述 原因分析: 解决方案: 项目场景: ffmpeg 剪切视频 问题描述 详细报错: [vost#0:0 @ 0x46ae00] Unknown encoder hevc_nvenc 原因分析: ffmpeg 安装错误 解决方案: 重新安装ffmpeg: conda install ffmpeg 检查当前安装的 FFmpeg 是否支…...
Kafka安全优化文档:漏洞修复到安全加固
文章目录 1.1.漏洞修复1.1.1.Apache Kafka反序列化漏洞1.1.2.pm2-kafka代码执行漏洞1.1.3.Apache Kafka安全绕过漏洞1.1.4.Apache Kafka Distribution - Schema Repository跨站请求伪造漏洞1.1.5.Apache Kafka输入验证错误漏洞的补丁1.1.6.Apache Kafka信息泄露漏洞1.1.7.Apach…...
Django 中数据库迁移命令
在 Django 中,python manage.py makemigrations、python manage.py sqlmigrate polls 0003 和 python manage.py migrate 是与数据库迁移相关的重要命令。它们的作用和对应内容如下: 1. python manage.py makemigrations 功能: 此命令会根据你的模型文…...
2024 高通边缘智能创新应用大赛智能边缘计算赛道冠军方案解读
2024 高通边缘智能创新应用大赛聚焦不同细分领域的边缘智能创新应用落地,共设立三大热门领域赛道——工业智能质检赛道、智能边缘计算赛道和智能机器人赛道。本文为智能边缘计算赛道冠军项目《端侧大模型智能翻译机》的开发思路与成果分享。 赛题要求 聚焦边缘智能…...
前端超大缓存IndexDB、入门及实际使用
文章目录 往期回顾项目实战初始化表获取列表新增表的数据项获取详情根据ID获取详情根据其他字段获取详情 删除数据 总结 往期回顾 在之前的文章中,我们介绍了IndexDB vs Cookies vs Session这几个的对比,但是没有做实际项目的演示,今天我们用…...
[创业之路-229]:《华为闭环战略管理》-5-平衡记分卡与战略地图
目录 一、平衡记分卡 1. 财务角度: 2. 客户角度: 3. 内部运营角度: 4. 学习与成长角度: 二、BSC战略地图 1、核心内容 2、绘制目的 3、绘制方法 4、注意事项 一、平衡记分卡 平衡记分卡(Balanced Scorecard&…...
形象地理解UE4中的数据结构 TLinkedListBase
大家都熟知链表,但不一定能快速看懂UE4中的数据结构。 TLinkedListBase表示“链接”中的一个结点,有三个成员: 一、ElementType Element; 表示具体的业务,例如int链条中的一个整数。 二、NextLink 表示 “下一个Node”&#…...
如何在谷歌浏览器中创建安全的密码
在数字化时代,网络安全变得日益重要。谷歌浏览器提供了多种工具和功能帮助用户创建和管理强密码,确保在线账户的安全。本文将简要介绍几种方法,帮助您在谷歌浏览器中创建和管理安全密码。 一、启用自动填充功能 确认密码保存功能已开启&…...
Nginx1.20.2-Linux-安装
文章目录 1.下载压缩包1.官网下载2.找到1.20.23.百度网盘 2.Linux安装1.搭建gcc环境2.上传到 /usr/local/nginx1.20.23.解压1.解压到当前目录2.删除压缩包 4.配置Nginx的编译路径1.进入nginx-1.20.22.执行内部的脚本,指定编译路径为/usr/local/nginx 5.编译并安装6.…...
网页版3D预览插件3dfindit
需求背景 如果你需要在浏览器上显示3D的模型,那么你可以看看这个3dfindit。不需要专业的代码开发,上传模型或者图片就行,他会自动生成3D预览。 效果图 // 效果图预览地址https://ksb-embedded.partcommunity.com/3d-cad-models/boa-compact…...
产品经理2025年展望
产品经理作为连接技术、设计与市场需求的桥梁,在快速变化的商业环境中扮演着至关重要的角色。展望2025年,随着技术的不断进步和消费者需求的日益多样化,产品经理的工作将面临更多挑战与机遇。 一、人工智能与自动化深化应用: 到…...
计算机找不到xinput1_3.dll无法执行怎么办?电脑缺失xinput1_3.dll文件怎么修复?
当计算机提示找不到xinput1_3.dll文件,导致某些程序或游戏无法执行时,可以采取以下步骤来修复这个问题: 一、了解xinput1_3.dll文件 xinput1_3.dll是Microsoft DirectX for Windows的控制模块,它包含了一组函数和数据结构&#…...
揭秘 Fluss 架构组件
这是 Fluss 系列的第四篇文章了,我们先回顾一下前面三篇文章主要说了哪些内容。 Fluss 部署,带领大家部署Fluss 环境,体验一下 Fluss 的功能Fluss 整合数据湖的操作,体验Fluss 与数据湖的结合讲解了 Fluss、Kafka、Paimon 之间的…...
你了解DNS吗?
你了解DNS吗? 一. 介绍二. DNS的工作原理三. DNS查询流程示意图四. DNS 记录类型五. DNS的安全问题与 DNSSEC 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 一. 介绍 …...
pyinstaller打包exe可执行文件
cd命令符进入要打包文件路径下,执行: 1.打包单个py文件,在控制台执行;dist下会生成2个文件,一个是exe文件 pyinstaller -D happy.py (cd命令符进入要打包文件路径下,执行) 打包单个py文件,在控制台执行;…...
leetcode108:将有序数组转化为二叉搜索树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。 示例 1: 输入:nums [-10,-3,0,5,9] 输出:[0,-3,9,-10,null,5] 解释:[0,-10,5,null,-3,null,9] 也将被视为正确…...
rust学习-初识rust
rust学习-初识rust 什么是 Rust?Rust 的特点什么是 Cargo?Cargo 的主要功能使用 Cargo 创建和管理项目Cargo.toml 文件详解常用 Cargo 命令什么是 Rustup?Rustup 的主要功能安装 Rustup验证安装使用 Rustup 管理工具链使用 Rustup 管理目标平…...
word怎么添加链接,点击直接到参考文献
word怎么添加链接,点击直接到参考文献 有时候并不一定非得latex https://download.csdn.net/download/qq_38998213/90199214 在Word中添加点击可直接跳转到参考文献的链接,主要有以下两种方法: 使用交叉引用和超链接结合的方法 插入参考文献: 首先,在文档中需要插入参考…...
数字赋能:制造企业如何靠“数字能力”实现可持续“超车”?
如今,制造业数字化转型可是个热门话题,全球都在积极推进。我国更是出台了一系列给力的政策来助力制造业数字化转型,像《中国制造 2025》就明确提出要加快制造业数字化、网络化、智能化发展,各省市也纷纷响应,从资金、税…...