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

Linux学习第28天:Platform设备驱动开发(二): 专注与分散

Linux版本号4.1.15   芯片I.MX6ULL                                    大叔学Linux    品人间百味  思文短情长 


三、硬件原理图分析

四、驱动开发

1、platform设备与驱动程序开发

53 /*
54 * 设备资源信息,也就是 LED0 所使用的所有寄存器
55 */
56 static struct resource led_resources[] = {
57 [0] = {
58 .start = CCM_CCGR1_BASE,
59 .end = (CCM_CCGR1_BASE + REGISTER_LENGTH - 1),
60 .flags = IORESOURCE_MEM,
61 },
62 [1] = {
63 .start = SW_MUX_GPIO1_IO03_BASE,
64 .end = (SW_MUX_GPIO1_IO03_BASE + REGISTER_LENGTH - 1),
65 .flags = IORESOURCE_MEM,
66 },
67 [2] = {
68 .start = SW_PAD_GPIO1_IO03_BASE,
69 .end = (SW_PAD_GPIO1_IO03_BASE + REGISTER_LENGTH - 1),
70 .flags = IORESOURCE_MEM,
71 },
72 [3] = {
73 .start = GPIO1_DR_BASE,
74 .end = (GPIO1_DR_BASE + REGISTER_LENGTH - 1),
75 .flags = IORESOURCE_MEM,
76 },
77 [4] = {
78 .start = GPIO1_GDIR_BASE,
79 .end = (GPIO1_GDIR_BASE + REGISTER_LENGTH - 1),
80 .flags = IORESOURCE_MEM,
81 },
82 };

        led_resources 数组,也就是设备资源,描述了 LED 所要使用到的寄存器信息,也就是 IORESOURCE_MEM 资源。

85 /*
86 * platform 设备结构体
87 */
88 static struct platform_device leddevice = {
89 .name = "imx6ul-led",
90 .id = -1,
91 .dev = {
92 .release = &led_release,
93 },
94 .num_resources = ARRAY_SIZE(led_resources),
95 .resource = led_resources,
96 };

        platform 设备结构体变量 leddevice,这里要注意 name 字段为“imx6ul-led”,所
以稍后编写 platform 驱动中的 name 字段也要为“imx6ul-led”,否则设备和驱动匹配失败。

98 /*
99 * @description : 设备模块加载
100 * @param : 无
101 * @return : 无
102 */
103 static int __init leddevice_init(void)
104 {
105 return platform_device_register(&leddevice);
106 }

        设备模块加载函数,在此函数里面通过 platform_device_register 向 Linux 内核注册 leddevice 这个 platform 设备。

108 /*
109 * @description : 设备模块注销
110 * @param : 无
111 * @return : 无
112 */
113 static void __exit leddevice_exit(void)
114 {
115 platform_device_unregister(&leddevice);
116 }

        设备模块卸载函数,在此函数里面通过 platform_device_unregister 从 Linux内核中删除掉 leddevice 这个 platform 设备。

34 #define LEDDEV_CNT 1 /* 设备号长度 */
35 #define LEDDEV_NAME "platled" /* 设备名字 */
36 #define LEDOFF 0
37 #define LEDON 1
38
39 /* 寄存器名 */
40 static void __iomem *IMX6U_CCM_CCGR1;
41 static void __iomem *SW_MUX_GPIO1_IO03;
42 static void __iomem *SW_PAD_GPIO1_IO03;
43 static void __iomem *GPIO1_DR;
44 static void __iomem *GPIO1_GDIR;
45
46 /* leddev 设备结构体 */
47 struct leddev_dev{
48 dev_t devid; /* 设备号 */
49 struct cdev cdev; /* cdev */
50 struct class *class; /* 类 */
51 struct device *device; /* 设备 */
52 int major; /* 主设备号 */
53 };
54
55 struct leddev_dev leddev; /* led 设备 */
56
57 /*
58 * @description : LED 打开/关闭
59 * @param - sta : LEDON(0) 打开 LED, LEDOFF(1) 关闭 LED
60 * @return : 无
61 */
62 void led0_switch(u8 sta)
63 {
64 u32 val = 0;
65 if(sta == LEDON){
66 val = readl(GPIO1_DR);
67 val &= ~(1 << 3);
68 writel(val, GPIO1_DR);
69 }else if(sta == LEDOFF){
70 val = readl(GPIO1_DR);
71 val|= (1 << 3);
72 writel(val, GPIO1_DR);
73 }
74 }
75
76 /*
77 * @description : 打开设备
78 * @param – inode : 传递给驱动的 inode
79 * @param - filp : 设备文件, file 结构体有个叫做 private_data 的成员变量
80 * 一般在 open 的时候将 private_data 指向设备结构体。
81 * @return : 0 成功;其他 失败
82 */
83 static int led_open(struct inode *inode, struct file *filp)
84 {
85 filp->private_data = &leddev; /* 设置私有数据 */
86 return 0;
87 }
88
89 /*
90 * @description : 向设备写数据
91 * @param – filp : 设备文件,表示打开的文件描述符
92 * @param - buf : 要写给设备写入的数据
93 * @param - cnt : 要写入的数据长度
94 * @param - offt : 相对于文件首地址的偏移
95 * @return : 写入的字节数,如果为负值,表示写入失败
96 */
97 static ssize_t led_write(struct file *filp, const char __user *buf,
size_t cnt, loff_t *offt)
98 {
99 int retvalue;
100 unsigned char databuf[1];
101 unsigned char ledstat;
102
103 retvalue = copy_from_user(databuf, buf, cnt);
104 if(retvalue < 0) {
105 return -EFAULT;
106 }
107
108 ledstat = databuf[0]; /* 获取状态值 */
109 if(ledstat == LEDON) {
110 led0_switch(LEDON); /* 打开 LED 灯 */
111 }else if(ledstat == LEDOFF) {
112 led0_switch(LEDOFF); /* 关闭 LED 灯 */
113 }
114 return 0;
115 }
116
117 /* 设备操作函数 */
118 static struct file_operations led_fops = {
119 .owner = THIS_MODULE,
120 .open = led_open,
121 .write = led_write,
122 };

        以上是传统的字符设备驱动。

124 /*
125 * @description : flatform 驱动的 probe 函数,当驱动与设备
126 * 匹配以后此函数就会执行
127 * @param - dev : platform 设备
128 * @return : 0,成功;其他负值,失败
129 */
130 static int led_probe(struct platform_device *dev)
131 {
132 int i = 0;
133 int ressize[5];
134 u32 val = 0;
135 struct resource *ledsource[5];
136
137 printk("led driver and device has matched!\r\n");
138 /* 1、获取资源 */
139 for (i = 0; i < 5; i++) {
140 ledsource[i] = platform_get_resource(dev, IORESOURCE_MEM, i);
141 if (!ledsource[i]) {
142 dev_err(&dev->dev, "No MEM resource for always on\n");
143 return -ENXIO;
144 }
145 ressize[i] = resource_size(ledsource[i]);
146 }
147
148 /* 2、初始化 LED */
149 /* 寄存器地址映射 */
150 IMX6U_CCM_CCGR1 = ioremap(ledsource[0]->start, ressize[0]);
151 SW_MUX_GPIO1_IO03 = ioremap(ledsource[1]->start, ressize[1]);
152 SW_PAD_GPIO1_IO03 = ioremap(ledsource[2]->start, ressize[2]);
153 GPIO1_DR = ioremap(ledsource[3]->start, ressize[3]);
154 GPIO1_GDIR = ioremap(ledsource[4]->start, ressize[4]);
155
156 val = readl(IMX6U_CCM_CCGR1);
157 val &= ~(3 << 26); /* 清除以前的设置 */
158 val |= (3 << 26); /* 设置新值 */
159 writel(val, IMX6U_CCM_CCGR1);
160
161 /* 设置 GPIO1_IO03 复用功能,将其复用为 GPIO1_IO03 */
162 writel(5, SW_MUX_GPIO1_IO03);
163 writel(0x10B0, SW_PAD_GPIO1_IO03);
164
165 /* 设置 GPIO1_IO03 为输出功能 */
166 val = readl(GPIO1_GDIR);
167 val &= ~(1 << 3); /* 清除以前的设置 */
168 val |= (1 << 3); /* 设置为输出 */
169 writel(val, GPIO1_GDIR);
170
171 /* 默认关闭 LED1 */
172 val = readl(GPIO1_DR);
173 val |= (1 << 3) ;
174 writel(val, GPIO1_DR);
175
176 /* 注册字符设备驱动 */
177 /*1、创建设备号 */
178 if (leddev.major) { /* 定义了设备号 */
179 leddev.devid = MKDEV(leddev.major, 0);
180 register_chrdev_region(leddev.devid, LEDDEV_CNT,
LEDDEV_NAME);
181 } else { /* 没有定义设备号 */
182 alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT,
LEDDEV_NAME);
183 leddev.major = MAJOR(leddev.devid);
184 }
185
186 /* 2、初始化 cdev */
187 leddev.cdev.owner = THIS_MODULE;
188 cdev_init(&leddev.cdev, &led_fops);
189
190 /* 3、添加一个 cdev */
191 cdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);
192
193 /* 4、创建类 */
194 leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);
195 if (IS_ERR(leddev.class)) {
196 return PTR_ERR(leddev.class);
197 }
198
199 /* 5、创建设备 */
200 leddev.device = device_create(leddev.class, NULL, leddev.devid,
NULL, LEDDEV_NAME);
201 if (IS_ERR(leddev.device)) {
202 return PTR_ERR(leddev.device);
203 }
204
205 return 0;
206 }

        probe 函数,当设备和驱动匹配以后此函数就会执行,当匹配成功以后会在终端上输出“led driver and device has matched!”这样语句。在 probe 函数里面初始化 LED、注册字符设备驱动。也就是将原来在驱动加载函数里面做的工作全部放到 probe 函数里面完成。

208 /*
209 * @description :移除 platform 驱动的时候此函数会执行
210 * @param - dev : platform 设备
211 * @return : 0,成功;其他负值,失败
212 */
213 static int led_remove(struct platform_device *dev)
214 {
215 iounmap(IMX6U_CCM_CCGR1);
216 iounmap(SW_MUX_GPIO1_IO03);
217 iounmap(SW_PAD_GPIO1_IO03);
218 iounmap(GPIO1_DR);
219 iounmap(GPIO1_GDIR);
220
221 cdev_del(&leddev.cdev); /* 删除 cdev */
222 unregister_chrdev_region(leddev.devid, LEDDEV_CNT);
223 device_destroy(leddev.class, leddev.devid);
224 class_destroy(leddev.class);
225 return 0;
226 }

        remove 函数,当卸载 platform 驱动的时候此函数就会执行。在此函数里面释放内存、注销字符设备等。也就是将原来驱动卸载函数里面的工作全部都放到 remove 函数中完成。

228 /* platform 驱动结构体 */
229 static struct platform_driver led_driver = {
230 .driver = {
231 .name = "imx6ul-led", /* 驱动名字,用于和设备匹配 */
232 },
233 .probe = led_probe,
234 .remove = led_remove,
235 };

        platform_driver 驱动结构体,注意 name 字段为"imx6ul-led",和我们在leddevice.c 文件里面设置的设备 name 字段一致。

237 /*
238 * @description : 驱动模块加载函数
239 * @param : 无
240 * @return : 无
241 */
242 static int __init leddriver_init(void)
243 {
244 return platform_driver_register(&led_driver);
245 }

        驱动模块加载函数,在此函数里面通过 platform_driver_register 向 Linux 内核注册 led_driver 驱动。

247 /*
248 * @description : 驱动模块卸载函数
249 * @param : 无
250 * @return : 无
251 */
252 static void __exit leddriver_exit(void)
253 {
254 platform_driver_unregister(&led_driver);
255 }

        驱动模块卸载函数,在此函数里面通过 platform_driver_unregister 从 Linux
内核卸载 led_driver 驱动。

2、测试APP开发

1 #include "stdio.h"
2 #include "unistd.h"
3 #include "sys/types.h"
4 #include "sys/stat.h"
5 #include "fcntl.h"
6 #include "stdlib.h"
7 #include "string.h"
8 /***************************************************************
9 Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
10 文件名 : ledApp.c
11 作者 : 左忠凯
12 版本 : V1.0
13 描述 : platform 驱动驱测试 APP。
14 其他 : 无
15 使用方法 : ./ledApp /dev/platled 0 关闭 LED
16 ./ledApp /dev/platled 1 打开 LED
17 论坛 : www.openedv.com
18 日志 : 初版 V1.0 2019/8/16 左忠凯创建
19 ***************************************************************/
20 #define LEDOFF 0
21 #define LEDON 1
22
23 /*
24 * @description : main 主程序
25 * @param - argc : argv 数组元素个数
26 * @param - argv : 具体参数
27 * @return : 0 成功;其他 失败
28 */
29 int main(int argc, char *argv[])
30 {
31 int fd, retvalue;
32 char *filename;
33 unsigned char databuf[2];
34
35 if(argc != 3){
36 printf("Error Usage!\r\n");
37 return -1;
38 }
39
40 filename = argv[1];
41 /* 打开 led 驱动 */
42 fd = open(filename, O_RDWR);
43 if(fd < 0){
44 printf("file %s open failed!\r\n", argv[1]);
45 return -1;
46 }
47
48 databuf[0] = atoi(argv[2]); /* 要执行的操作:打开或关闭 */
49 retvalue = write(fd, databuf, sizeof(databuf));
50 if(retvalue < 0){
51 printf("LED Control Failed!\r\n");
52 close(fd);
53 return -1;
54 }
55
56 retvalue = close(fd); /* 关闭文件 */
57 if(retvalue < 0){
58 printf("file %s close failed!\r\n", argv[1]);
59 return -1;
60 }
61 return 0;
62 }

五、运行测试

1、编译驱动程序和测试APP

4 obj-m := leddevice.o leddriver.o

        设置 obj-m 变量的值为“leddevice.o leddriver.o”。

        输入如下命令编译出驱动模块文件:
                make -j32
        编译成功以后就会生成一个名为“leddevice.ko leddriver.ko”的驱动模块文件。

        输入如下命令编译测试 ledApp.c 这个测试程序:
                arm-linux-gnueabihf-gcc ledApp.c -o ledApp
        编译成功以后就会生成 ledApp 这个应用程序。

2、运行测试

depmod //第一次加载驱动的时候需要运行此命令
modprobe leddevice.ko //加载设备模块
modprobe leddriver.ko //加载驱动模块

        根文件系统中/sys/bus/platform/目录下保存着当前板子 platform 总线下的设备和驱动,其中
devices 子目录为 platform 设备, drivers 子目录为 plartofm 驱动。查看/sys/bus/platform/devices/
目录,看看我们的设备是否存在,我们在 leddevice.c 中设置 leddevice(platform_device 类型)的
name 字段为“imx6ul-led”,也就是设备名字为 imx6ul-led,因此肯定在/sys/bus/platform/devices/
目录下存在一个名字“imx6ul-led”的文件,否则说明我们的设备模块加载失败,结果如图 所示:

        查看/sys/bus/platform/drivers/目录,看一下驱动是否存在,我们在 leddriver.c 中设置
led_driver (platform_driver 类型)的 name 字段为“imx6ul-led”,因此会在/sys/bus/platform/drivers/
目录下存在名为“imx6ul-led”这个文件,结果如图 所示:

驱动模块和设备模块加载成功以后 platform 总线就会进行匹配,当驱动和设备匹配成功以
后就会输出如图 所示一行语句:

        驱动和设备匹配成功以后就可以测试 LED 灯驱动了,输入如下命令打开 LED 灯:

/ledApp /dev/platled 1 //打开 LED 灯


        在输入如下命令关闭 LED 灯:

./ledApp /dev/platled 0 //关闭 LED 灯


        观察一下 LED 灯能否打开和关闭,如果可以的话就说明驱动工作正常,如果要卸载驱动的
话输入如下命令即可:
rmmod leddevice.ko
rmmod leddriver.ko

六、总结:

        本篇笔记主要学习了platform设备驱动开发的相关概念。将分成两次笔记进行学习。本次笔记主要学习platform设备驱动开发相关的理论知识。主要内容包括:Linux驱动的分离与分层、platform平台驱动模型简介。其中驱动的分离与分层有包括驱动的分离、驱动的分层。platform平台驱动模型简介主要包括platform总线、platform驱动与platform设备。
————————————————
版权声明:本文为CSDN博主「大叔学Linux」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jiage987450/article/details/134125677        


本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。

相关文章:

Linux学习第28天:Platform设备驱动开发(二): 专注与分散

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 三、硬件原理图分析 四、驱动开发 1、platform设备与驱动程序开发 53 /* 54 * 设备资源信息&#xff0c;也就是 LED0 所使用的所有寄存器 55 */ 56 static str…...

postgresql数组重叠(有共同元素)查询

直接上最终代码&#xff1a; select distinct id from a where string_to_array(in_area,,) && (select ARRAY_AGG( code) from areas where code like 11% or code 100000)::TEXT[] pg语法&#xff1a; 表 9.48显示了可用于数组类型的运算符。 表 9.48。数组运算符…...

ubuntu系统 生成RSA密钥对

在Ubuntu系统上生成密钥对通常指的是生成SSH密钥对&#xff0c;它常用于安全的远程登录、数据通信和其他安全网络操作。以下是如何在Ubuntu系统上生成SSH密钥对的步骤&#xff1a; 打开终端&#xff1a;你可以使用快捷键 Ctrl Alt T 在Ubuntu上打开一个终端窗口。 运行ssh-k…...

【RtpSeqNumOnlyRefFinder】webrtc m98: ManageFrameInternal 的帧决策过程分析

Jitterbuffer(FrameBuffer)需要组帧以后GOP内的参考关系 JeffreyLau 大神分析 了组帧原理而参考关系(RtpFrameReferenceFinder)的生成伴随了帧决策 FrameDecisionFrameDecision 影响力 帧的缓存。调用 OnAssembledFrame 传递已经拿到的RtpFrameObject 那么,RtpFrameObject…...

centos系统源码编译安装nginx,并编写服务脚本

1.安装编译所需的依赖项&#xff1a; yum install -y gcc pcre-devel openssl-devel zlib-devel2.下载 Nginx 源代码&#xff1a; wget http://nginx.org/download/nginx-1.21.3.tar.gz tar -xf nginx-1.21.3.tar.gz cd nginx-1.21.33.配置编译选项并进行编译和安装&#xff…...

2023下半年软考高项答题技巧!

2023下半年软考倒计时最后一天&#xff0c;一些软考高项答题技巧分享&#xff01; 高项答题技巧 1、综合知识 &#xff08;1&#xff09;首先是分析试题的技巧 –先看清楚问题&#xff0c;再看选项&#xff1b; –判断题目到底考察的是什么知识点&#xff0c;排除干扰项。…...

windows server 2016调优

1. 增加TCP连接的最大数量&#xff1a; 在您当前的注册表路径&#xff08;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters&#xff09;中的右侧窗格&#xff0c;右击空白处&#xff0c;选择“新建” -> “DWORD (32位) 值”。为新的值命名为TcpNu…...

Qt 插件开发详解

1.简介 Qt插件是一种扩展机制&#xff0c;用于将应用程序的功能模块化&#xff0c;并且可以在运行时动态加载和卸载。Qt框架为插件提供了一套标准的接口和管理机制&#xff0c;使得插件的使用和集成变得简单和灵活&#xff0c;通过插件机制&#xff0c;可以将应用程序的功能划…...

vue需求:实现签章/签字在页面上自由定位的功能(本质:元素在页面上的拖拽)

目录 第一章 效果展示 第二章 了解工具 2.1 draggable 2.1.1 了解draggable 2.1.2 draggable方法 2.1.3 利用例子理解方法 第三章 效果实现 3.1 实现思路 3.2 代码实现 3.2.1 涉及到的点 3.2.2 源代 第一章 效果展示 效果描述&#xff1a;通过点击左边栏的签名和…...

【深度学习基础】Pytorch框架CV开发(1)基础铺垫

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

uniapp原生插件之安卓热敏打印机打印插件

插件介绍 安卓热敏打印机打印插件&#xff0c;自动授权&#xff0c;打印机连接监听&#xff0c;打印文本&#xff0c;条形码&#xff0c;二维码&#xff0c;切纸&#xff0c;打印机状态&#xff0c;打印结果查询等 插件地址 安卓热敏打印机打印插件 - DCloud 插件市场 超级…...

巴菲特:卖比亚迪有助于资金配置

巴菲特表示&#xff0c;未来可能会有更多银行倒闭&#xff0c;但储户不必担心&#xff0c;他警告说&#xff0c;陷入困境的银行股不是价值投资&#xff0c;因为即使政府采取行动保护储户&#xff0c;股东的权益也会受到损失。他称&#xff0c;将加大对日本综合商社的投资&#…...

香港服务器有哪些特点

香港服务器具有以下特点&#xff1a; 速度快&#xff1a;香港服务器地理位置优越&#xff0c;与内地服务器相比&#xff0c;网络延迟更低&#xff0c;访问速度更快。 稳定性高&#xff1a;香港服务器位于全球重要的金融中心&#xff0c;网络环境稳定&#xff0c;服务器稳定性高…...

Leetcode76最小覆盖子串

思路&#xff1a;滑动窗口思想 1. 滑动窗口是什么&#xff1a;用一个滑动窗口为覆盖目标子串的字符串 2.怎么移动窗口&#xff1a;当不满足覆盖时右指针移动扩大范围&#xff0c;当覆盖了就移动左指针缩减范围直到再次不覆盖 3. 怎么判断是否覆盖&#xff1a;这里使用两个哈…...

GD32 单片机 硬件I2C死锁解决方法

死锁的复现方式 在I2C恢复函数下个断点&#xff08;检测到I2C多次超时之后&#xff0c;应该能跳转到I2C恢复函数&#xff09;使用镊子&#xff0c;将SCL与SDA短接&#xff0c;很快就能看到程序停到恢复函数的断点上&#xff0c;此时再执行恢复函数&#xff0c;看能否正常走出&…...

SPSS两相关样本检验

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…...

【vscode远程开发】使用内网穿透实现在公网环境下远程访问

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…...

KaiwuDB 内核解析 - SQL 查询的生命周期

一、概述 KaiwuDB 内核解析系列共分上下两部分&#xff0c;本文是该系列的第一部分&#xff0c;主要涵盖了网络协议到 SQL 执行器&#xff0c;解释 KaiwuDB 如何执行 SQL 查询&#xff0c;包括系统各个组件的执行路径&#xff08;网络协议、SQL 会话管理、解析器、执行计划及优…...

2023.11.03 homework

小学4年级数学 1 2 3 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 19…...

ssm在线互助答疑系统-计算机毕设 附源码 20862

ssm在线互助答疑系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

一些实用的chrome扩展0x01

简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序&#xff0c;无论是测试应用程序、搜寻漏洞还是收集情报&#xff0c;它们都能提升工作流程。 FoxyProxy 代理管理工具&#xff0c;此扩展简化了使用代理&#xff08;如 Burp…...