Linux LED 实验
一、Linux 下 LED 灯驱动原理
其实跟裸机实验很相似,只不过要编写符合 Linux 的驱动框架。
1. 地址映射
MMU全称 Memory Manage Unit,即内存存储单元。
MMU主要功能为:
1)完成虚拟空间到物理空间的映射;
2)内存保护,设置存储器的访问权限,设置虚拟存储空间的缓冲特性。
Linux 内核启动的时候会初始化 MMU,设置好内存映射。
原来的裸机实验,是直接对 GPIO1_IO03 引脚的复用寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的地址0X020E0068写入数据。
但是现在开启了 Linux 内核后,MMU设置了内存映射,不能向原先的地址写入数据了。那么必须要得到 0X020E0068 对应的虚拟地址。
1.1 ioremap 函数
该函数用于获取物理地址空间对应的虚拟地址空间,定义在 arch/arm/include/asm/io.h 文件中。
我们查看 ioremap 函数原型
#define ioremap(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) void __iomem * __arm_ioremap(phys_addr_t phys_addr, size_t size, unsigned int mtype)
{ return arch_ioremap_caller(phys_addr, size, mtype, __builtin_return_address(0));
}
phys_addr:要映射的物理起始地址。
size:要映射的内存空间大小。
mtype:ioremap 的类型,可以选择 MT_DEVICE、MT_DEVICE_NONSHARED、MT_DEVICE_CACHED 和 MT_DEVICE_WC,ioremap 函数选择 MT_DEVICE。
返回值:__iomem 类型的指针,指向映射后的虚拟空间首地址。
要获取IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 寄存器对应 的虚拟地址,使用如下代码即可:
#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
static void __iomem* SW_MUX_GPIO1_IO03;
SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
宏 SW_MUX_GPIO1_IO03_BASE 是寄存器物理地址,SW_MUX_GPIO1_IO03 是映射后 的虚拟地址。对于 I.MX6ULL 来说一个寄存器是 4 字节(32 位)的,因此映射的内存长度为 4。
1.2 iounmap 函数
卸载驱动的时候需要使用 iounmap 函数释放掉 ioremap 函数所做的映射。
比如上面的驱动进行卸载
iounmap(SW_MUX_GPIO1_IO03);
2. IO内存访问函数
Linux 内核提供一组操作函数对映射后的内存进行读写操作。
2.1 读操作函数
u8 readb(const volatile void __iomem *addr)
u16 readw(const volatile void __iomem *addr)
u32 readl(const volatile void __iomem *addr)
readb、readw 和 readl 这三个函数分别对应 8bit、16bit 和 32bit 读操作,参数 addr 就是要 读取写内存地址,返回值就是读取到的数据。 。
2.2 写操作函数
void writeb(u8 value, volatile void __iomem *addr)
void writew(u16 value, volatile void __iomem *addr)
void writel(u32 value, volatile void __iomem *addr)
writeb、writew 和 writel 这三个函数分别对应 8bit、16bit 和 32bit 写操作,参数 value 是要 写入的数值,addr 是要写入的地址。
二、 硬件原理
STM32和IM6ULL的裸机实验有介绍了,就不赘述了。
三、实验程序编写
1. 驱动程序编写
首先寄存器的物理地址
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE (0X020E02F4)
#define GPIO1_DR_BASE (0X0209C000)
#define GPIO1_GDIR_BASE (0X0209C004)
虚拟地址指针
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;
LED 灯的开关
void led_switch(u8 sta)
{ u32 val = 0; if(sta == LEDON) { val = readl(GPIO1_DR); val &= ~(1 << 3); writel(val, GPIO1_DR); }else if(sta == LEDOFF) { val = readl(GPIO1_DR); val|= (1 << 3); writel(val, GPIO1_DR); }
}
打开设备
static int led_open(struct inode *inode, struct file *filp)
{ return 0;
}
从设备读取数据
static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{ return 0;
}
向设备写数据
static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{ int retvalue; unsigned char databuf[1]; unsigned char ledstat; retvalue = copy_from_user(databuf, buf, cnt); if(retvalue < 0) { printk("kernel write failed!\r\n"); return -EFAULT; } ledstat = databuf[0]; /* 获取状态值 */ if(ledstat == LEDON) { led_switch(LEDON); /* 打开 LED 灯 */ } else if(ledstat == LEDOFF) { led_switch(LEDOFF); /* 关闭 LED 灯 */ } return 0; }
关闭/释放设备
121 static int led_release(struct inode *inode, struct file *filp)
122 {
123 return 0;
124 }
设备操作函数
static struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .read = led_read, .write = led_write, .release = led_release,
};
驱动入口函数
static int __init led_init(void)
{ int retvalue = 0; u32 val = 0; /* 初始化 LED */ /* 1、寄存器地址映射 */ IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4); SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4); SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4); GPIO1_DR = ioremap(GPIO1_DR_BASE, 4); GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4); /* 2、使能 GPIO1 时钟 */ val = readl(IMX6U_CCM_CCGR1); val &= ~(3 << 26); /* 清除以前的设置 */ val |= (3 << 26); /* 设置新值 */ writel(val, IMX6U_CCM_CCGR1); /* 3、设置 GPIO1_IO03 的复用功能,将其复用为 * GPIO1_IO03,最后设置 IO 属性。 */ writel(5, SW_MUX_GPIO1_IO03); /* 寄存器 SW_PAD_GPIO1_IO03 设置 IO 属性 */ writel(0x10B0, SW_PAD_GPIO1_IO03); /* 4、设置 GPIO1_IO03 为输出功能 */ val = readl(GPIO1_GDIR); val &= ~(1 << 3); /* 清除以前的设置 */ val |= (1 << 3); /* 设置为输出 */ writel(val, GPIO1_GDIR); /* 5、默认关闭 LED */ val = readl(GPIO1_DR); val |= (1 << 3); writel(val, GPIO1_DR); /* 6、注册字符设备驱动 */ retvalue = register_chrdev(LED_MAJOR, LED_NAME, &led_fops); if(retvalue < 0){ printk("register chrdev failed!\r\n"); return -EIO; } return 0;
}
驱动出口函数
static void __exit led_exit(void)
{ /* 取消映射 */ iounmap(IMX6U_CCM_CCGR1); iounmap(SW_MUX_GPIO1_IO03); iounmap(SW_PAD_GPIO1_IO03); iounmap(GPIO1_DR); iounmap(GPIO1_GDIR); /* 注销字符设备驱动 */ unregister_chrdev(LED_MAJOR, LED_NAME); } module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Prover");
2. 编写测试程序
这时候需要用的 Linux C了,在 Linux 系统下,一切皆文件。应用层如何操控底层硬件,同样也是通过文件 I/O 的方式来实现。设备文件通常在/dev/目录下,我们也把/dev 目录下的文件称为设备节点。除此之外,我们还可以通过 sysfs 文件系统对硬件设备进行 操控。
对于 ALPHA/Mini I.MX6U 开发板出厂系统来说,此 LED 设备使用的是 Linux 内核标准 LED 驱动框架 注册而成,在/dev 目录下并没有其对应的设备节点,其实现使用 sysfs 方式控制。
2.1 sysfs 文件系统
请注意,驱动开发先别看这里,因为需要先 mfgtool 把系统文件烧好,然后直接进入系统,而不是和平时驱动开发那样,根文件是挂载的情况。
sysfs 是一个基于内存的文件系统,同 devfs、proc 文件系统一样,称为虚拟文件系统;它的 作用是将内核信息以文件的方式提供给应用层使用。
sysfs 文件系统挂载在/sys 目录下
进入到/sys/class/leds 目录 下,如果找不到 sys-led 文件,说明你移植的根文件系统是原产的。

brightness、max_brightness 以及 trigger 三个文件,这三个文件都是 LED 设备的 属性文件:
brightness:翻译过来就是亮度的意思,该属性文件可读可写;
max_brightness:该属性文件只能被读取,不能写,用于获取 LED 设备的最大亮度等级。
trigger:触发模式,该属性文件可读可写,读表示获取 LED 当前的触发模式,写表示设置 LED 的 触发模式。通过 cat 命令查看该属性文件。

方括号([heartbeat])括起来的表示当前 LED 对应的触发模式,none 表示无触发,常用的触发模式包括 none(无触发)、mmc0(当对 mmc0 设备发起读写操作的时候 LED 会闪烁)、timer(LED 会有规律的一 亮一灭,被定时器控制住)、heartbeat(心跳呼吸模式,LED 模仿人的心跳呼吸那样亮灭变化)。
通过 echo 命令进行控制:
echo timer > trigger //将 LED 触发模式设置为 timer echo none > trigger //将 LED 触发模式设置为 none
echo 1 > brightness //点亮 LED echo 0 > brightness//熄灭 LED
编写应用程序
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h> #define LED_TRIGGER "/sys/class/leds/sys-led/trigger"
#define LED_BRIGHTNESS "/sys/class/leds/sys-led/brightness"
#define USAGE() fprintf(stderr, "usage:\n" \ " %s <on|off>\n" \ " %s <trigger> <type>\n", argv[0], argv[0]) int main(int argc, char *argv[])
{ int fd1, fd2; /* 校验传参 */ if (2 > argc) { USAGE(); exit(-1); } /* 打开文件 */ fd1 = open(LED_TRIGGER, O_RDWR); if (0 > fd1) { perror("open error"); exit(-1); } fd2 = open(LED_BRIGHTNESS, O_RDWR); if (0 > fd2) { perror("open error"); exit(-1); } /* 根据传参控制 LED */ if (!strcmp(argv[1], "on")) { write(fd1, "none", 4); //先将触发模式设置为 none write(fd2, "1", 1); //点亮 LED } else if (!strcmp(argv[1], "off")) { write(fd1, "none", 4); //先将触发模式设置为 none write(fd2, "0", 1); //LED 灭 } else if (!strcmp(argv[1], "trigger")) { if (3 != argc) { USAGE(); exit(-1); } if (0 > write(fd1, argv[2], strlen(argv[2]))) perror("write error"); } else USAGE(); exit(0);
}
然后使能编译环境
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

CC变量就是交叉编译工具。
编译程序,并把可执行文件拷贝到开发板上。然后运行并添加参数。

2.2 dev 文件系统
这里是正统的驱动方式,跟上个字符设备驱动开发的方式是一样的。
用内核源码的 include,以及开发板的内核和驱动是同源的。
编译成功以后就会生成一个名为“led.ko”的驱动模块文件。
led 驱动加载后,手动创建 /dev/led 节点,然后向 /dev/led 文件写 0 关闭灯,写 1 开启灯。
ledApp.c 的源码如下:
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"#define LEDOFF 0
#define LEDON 1/** @description : main主程序* @param - argc : argv数组元素个数* @param - argv : 具体参数* @return : 0 成功;其他 失败*/
int main(int argc, char *argv[])
{int fd, retvalue;char *filename;unsigned char databuf[1];if(argc != 3){printf("Error Usage!\r\n");return -1;}filename = argv[1];/* 打开led驱动 */fd = open(filename, O_RDWR);if(fd < 0){printf("file %s open failed!\r\n", argv[1]);return -1;}databuf[0] = atoi(argv[2]); /* 要执行的操作:打开或关闭 *//* 向/dev/led文件写入数据 */retvalue = write(fd, databuf, sizeof(databuf));if(retvalue < 0){printf("LED Control Failed!\r\n");close(fd);return -1;}retvalue = close(fd); /* 关闭文件 */if(retvalue < 0){printf("file %s close failed!\r\n", argv[1]);return -1;}return 0;
}
以及 Makefile 文件
KERNELDIR := /home/prover/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
CURRENT_PATH := $(shell pwd)obj-m := led.obuild: kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modulesclean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
测试文件同样使用交叉编译器来编译。
arm-linux-gnueabihf-gcc ledApp.c -o ledApp
最后,将 .ko 和 测试文件 拷贝到 rootfs 的 lib/modules/4.1.15 下。
sudo cp ledApp led.ko /home/prover/linux/nfs/rootfs/lib/modules/4.1.15/

由于是第一次加载驱动,先 depmod 然后再 modprobe led.ko。
然后创建 /dev/led 设备节点:
mknod /dev/led c 200 0
随后,测试:
./ledApp /dev/led 1
最后把驱动卸载
rmmod led.ko
2.3 Qt 应用
其实就是通过 sysfs 文件系统来控制 led 的亮灭。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPushButton>
#include <QFile>class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:/* 按钮 */QPushButton *pushButton;/* 文件 */QFile file;/* 设置lED的状态 */void setLedState();/* 获取lED的状态 */bool getLedState();private slots:void pushButtonClicked();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QDebug>
#include <QGuiApplication>
#include <QScreen>
#include <QRect>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{/* 获取屏幕的分辨率,Qt官方建议使用这* 种方法获取屏幕分辨率,防上多屏设备导致对应不上* 注意,这是获取整个桌面系统的分辨率*/QList <QScreen *> list_screen = QGuiApplication::screens();/* 如果是ARM平台,直接设置大小为屏幕的大小 */
#if __arm__/* 重设大小 */this->resize(list_screen.at(0)->geometry().width(),list_screen.at(0)->geometry().height());/* 默认是出厂系统的LED心跳的触发方式,想要控制LED,* 需要改变LED的触发方式,改为none,即无 */system("echo none > /sys/class/leds/sys-led/trigger");
#else/* 否则则设置主窗体大小为800x480 */this->resize(800, 480);
#endifpushButton = new QPushButton(this);/* 居中显示 */pushButton->setMinimumSize(200, 50);pushButton->setGeometry((this->width() - pushButton->width()) /2 ,(this->height() - pushButton->height()) /2,pushButton->width(),pushButton->height());/* 开发板的LED控制接口 */file.setFileName("/sys/devices/platform/leds/leds/sys-led/brightness");if (!file.exists())/* 设置按钮的初始化文本 */pushButton->setText("未获取到LED设备!");/* 获取LED的状态 */getLedState();/* 信号槽连接 */connect(pushButton, SIGNAL(clicked()),this, SLOT(pushButtonClicked()));
}MainWindow::~MainWindow()
{
}void MainWindow::setLedState()
{/* 在设置LED状态时先读取 */bool state = getLedState();/* 如果文件不存在,则返回 */if (!file.exists())return;if(!file.open(QIODevice::ReadWrite))qDebug()<<file.errorString();QByteArray buf[2] = {"0", "1"};/* 写0或1 */if (state)file.write(buf[0]);elsefile.write(buf[1]);/* 关闭文件 */file.close();/*重新获取LED的状态 */getLedState();
}bool MainWindow::getLedState()
{/* 如果文件不存在,则返回 */if (!file.exists())return false;if(!file.open(QIODevice::ReadWrite))qDebug()<<file.errorString();QTextStream in(&file);/* 读取文件所有数据 */QString buf = in.readLine();/* 打印出读出的值 */qDebug()<<"buf: "<<buf<<endl;file.close();if (buf == "1") {pushButton->setText("LED点亮");return true;} else {pushButton->setText("LED熄灭");return false;}
}void MainWindow::pushButtonClicked()
{/* 设置LED的状态 */setLedState();
}
通过 Qt 编译(或者直接编写Makefile)的可执行文件,传输到开发板上。
在串口 xtem 终端上运行可执行文件。会发现界面直接覆盖了开发板的整个 UI。
相关文章:
Linux LED 实验
一、Linux 下 LED 灯驱动原理 其实跟裸机实验很相似,只不过要编写符合 Linux 的驱动框架。 1. 地址映射 MMU全称 Memory Manage Unit,即内存存储单元。 MMU主要功能为: 1)完成虚拟空间到物理空间的映射; 2&#x…...
深入解析:Jsoup 库的多功能应用场景
Jsoup 是一个强大的 Java 库,主要用于解析和操作 HTML 文档。它不仅广泛应用于网络爬虫和数据抓取,还在网页内容分析、数据清洗与处理、自动化测试等多个领域有着广泛的应用。本文将详细介绍 Jsoup 库的多种用途,并提供具体的代码示例。 一、…...
直接抓取网页的爬虫技术:限制与合规挑战
在利用爬虫技术直接抓取网页内容时,尤其是针对像淘宝这样的大型电商平台,开发者可能会面临诸多技术限制和法律风险。这些限制不仅影响爬虫的效率,还可能引发法律问题。因此,了解这些限制并采取合规措施至关重要。 一、直接抓取网…...
docker常用命令及案例
以下是 Docker 的所有常用命令及其案例说明,按功能分类整理: 1. 镜像管理 1.1 拉取镜像 命令: docker pull <镜像名>:<标签>案例: 拉取官方的 nginx 镜像docker pull nginx:latest1.2 列出本地镜像 命令: docker images案例: 查看本地所有…...
【Redis】redis 存储的列表如何分页和检索
博主介绍:✌全网粉丝22W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
2025.2.6 数模AI智能体大更新,更专业的比赛辅导,同提示词效果优于gpt-o1/o3mini、deepseek-r1满血
本次更新重新梳理了回复逻辑规则,无任何工作流,一共3.2k字细节描述。具体效果可以看视频,同时也比对了gpt-o1、gpt-o3mini、deepseek-r1-67BI,从数学建模题目解答上来看,目前我的数模AI智能体具有明显优势。 AI智能体优…...
如何在 Linux 中管理自定义脚本:将 ~/bin 目录添加到 $PATH
1. 前言 在 Linux Shell 中,$PATH 是一个非常重要的环境变量,它决定了系统在哪里寻找可执行命令。通过为 $PATH 添加自定义目录,你就能在任意位置方便地调用自己写的脚本或程序。本文将围绕这一主题,结合示例脚本 mycmd 以及 .ba…...
[LUA ERROR] bad light userdata pointer
Cocos2d项目,targetSdkVersion30,在 android 13 设备运行报错: [LUA ERROR] bad light userdata pointer ,导致黑屏。 参考 https://blog.csdn.net/sdsabc2000/article/details/135384162的方法 下载最新的Cocos2dx 4.0,将其中的luajit &am…...
cursor指令工具
Cursor 工具使用指南与实例 工具概览 Cursor 提供了一系列强大的工具来帮助开发者提高工作效率。本指南将通过具体实例来展示这些工具的使用方法。 1. 目录文件操作 1.1 查看目录内容 (list_dir) 使用 list_dir 命令可以查看指定目录下的文件结构: 示例: list_dir log…...
【玩转全栈】----Django模板语法、请求与响应
目录 一、引言 二、模板语法 三、传参 1、视图函数到模板文件 2、模板文件到视图函数 四、引入静态文件 五、请求与响应 ?1、请求 2、响应 六、综合小案例 1、源码展示 2、注意事项以及部分解释 3、展示 一、引言 像之前那个页面,太过简陋,而且一个完整…...
2025年2月9日(数据分析,在最高点和最低点添加注释,添加水印)
要在最高点和最低点添加文本注释,可以使用 plt.annotate() 函数。这个函数允许你在图表中的特定位置添加文本注释,并且可以指定箭头指向特定的数据点。 以下是修改后的代码,添加了在最高点和最低点的文本注释: from matplotlib import pyplot as plt from matplotlib imp…...
C++,设计模式,【单例模式】
文章目录 一、模式定义与核心价值二、模式结构解析三、关键实现技术演进1. 基础版(非线程安全)2. 线程安全版(双重检查锁)3. 现代C++实现(C++11起)四、实战案例:全局日志管理器五、模式优缺点深度分析✅ 核心优势⚠️ 潜在缺陷六、典型应用场景七、高级实现技巧1. 模板化…...
今日AI和商界事件(2025-02-08)
今日AI领域的重大事件主要包括以下几个方面: 一、DeepSeek引发的行业震动 事件概述:DeepSeek作为近期崛起的AI模型,以其低成本、高性能的推理能力引发了广泛关注。其开源策略、独特的出身以及强大的算力表现,使得微软、英伟达等…...
C# LINQ与集合类 数据操作
目录 LINQ语法 过滤数据 投影数据 排序数据 集合操作 聚合操作 分组操作 查找元素 其他操作 常用的集合类 List LinkedList HashSet Dictionary List:动态数组 LinkedList:双向链表 HashSet:唯一无序集合 Dictionary&…...
开源流程引擎对比:compileflow、Turbo、Warm-Flow、 flowable、activiti
文章目录 开源流程引擎对比I 工作流引擎阿里的Compileflowflowableactivitiwarm-flow(国产)Turbo (didiopensource)II 知识扩展开发流程开源流程引擎对比 ActivitiCamundaCompileflowturbo核心表量282205特性 中断可重入√√√支持回滚√√运行模式独立运行和内嵌独立运行和…...
golang使用sqlite3,开启wal模式,并发读写
因为sqlite是基于文件的,所以默认情况下,sqlite是不支持并发读写的,即写操作会阻塞其他操作,同时sqlite也很容易就产生死锁。 但是作为一个使用广泛的离线数据库,从sqlite3.7.0版本开始(SQLite Release 3.…...
基于yolov11的阿尔兹海默症严重程度检测系统python源码+onnx模型+评估指标曲线+精美GUI界面
【算法介绍】 基于YOLOv11的阿尔兹海默症严重程度检测系统是一种创新的医疗辅助工具,旨在通过先进的计算机视觉技术提高阿尔兹海默症的早期诊断和病情监测效率。阿尔兹海默症是一种渐进性的神经退行性疾病,通常表现为认知障碍、记忆丧失和语言障碍等症状…...
UV - Python 包管理
文章目录 创建 uv 项目已有项目已有uv项目 创建 uv 项目 # 创建项目 uv init m3 # 创建环境 cd m3 uv venv --python 3.11 # 激活环境 source .venv/bin/activate # 添加库 uv add flask 如果创建项目后,给库取别的名字,add 的时候,会…...
设计模式-生产者消费者模型
阻塞队列: 在介绍生产消费者模型之前,我们先认识一下阻塞队列。 阻塞队列是一种支持阻塞操作的队列,常用于生产者消费者模型,它提供了线程安全的队列操作,并且在队列为空或满时,能够阻塞等待,…...
RabbitMQ介绍以及基本使用
文章目录 一、什么是消息队列? 二、消息队列的作用(优点) 1、解耦 2、流量削峰 3、异步 4、顺序性 三、RabbitMQ基本结构 四、RabbitMQ队列模式 1、简单队列模式 2、工作队列模式 3、发布/订阅模式 4、路由模式 5、主题模式 6、…...
shell解决xml文本中筛选的问题
shell解决xml文本中筛选的问题,将xml文件中多余的配置删除掉,达到符合单一配置的结果。 过于简单就不废话了。 #!/bin/bashconf_file$1 flag0 temp_file"__temp.xml"if [ -f "${temp_file}" ];thenrm "${temp_file}" fi …...
嵌入式硬件篇---OpenMV的硬件流和软件流
文章目录 前言一、硬件流控制(Hardware Flow Control)1. 基本原理RTSCTS 2. OpenMV中的实现• 硬件要求• 代码配置• 工作流程 二、软件流控制(Software Flow Control)1. 基本原理XONXOFF 2. OpenMV中的实现• 代码配置• 工作流…...
1.6 学习测试用例(Test)分为几步?
文章目录 前言一、什么是UVM中的测试用例(Test)?二、如何理解UVM中的测试用例?三、如何使用UVM中的测试用例?四、实操代码示例4.1代码结构4.2 代码实现4.2.1 a. 测试用例类的定义和实现4.2.2 b. 测试环境的构建和配置4…...
PDF2.0 投影注释(Projection annotations)
投影注释是PDF2.0新标准中新增加的注释类型,属于标记注释的子类型,因此,它具有很多其他标记注释的功能。 然而,投影注释仅在特定的运行时环境的上下文中有效,例如已激活的3D模型。 投影注释的注释字典包含了所有注释字…...
【AIGC提示词系统】基于 DeepSeek R1 + ClaudeAI 易经占卜系统
上篇因为是VIP,这篇来一个免费的 提示词在最下方,喜欢的点个关注吧 引言 在人工智能与传统文化交融的今天,如何让AI系统能够传递传统易经文化的智慧,同时保持易经本身的神秘感和权威性,是一个极具挑战性的课题。本文将…...
OpenAI 实战进阶教程 - 第十节 : 结合第三方工具的向量数据库Pinecone
面向读者群体 本节课程主要面向有一定编程基础和数据处理经验的计算机从业人员,如后端开发工程师、数据工程师以及对 AI 应用有浓厚兴趣的技术人员。即使你之前没使用过向量数据库,也可以通过本节的实操内容快速上手,为企业或个人项目构建强…...
深入Linux系列之进程地址空间
深入Linux系列之进程地址空间 1.引入 那么在之前的学习中,我们知道我们创建一个子进程的话,我们可以在代码层面调用fork函数来创建我们的子进程,那么fork函数的返回值根据我们当前所处进程的上下文是返回不同的值,它在父进程中返…...
AWK系统学习指南:从文本处理到数据分析的终极武器 介绍
目录 一、AWK核心设计哲学解析 1.1 记录与字段的原子模型 1.2 模式-动作范式 二、AWK编程语言深度解析 2.1 控制结构 说明: 2.2 关联数组 代码说明: 示例输入和输出: 注意事项: 2.3 内置函数库 三、高级应用技巧 3.1…...
250207-MacOS修改Ollama模型下载及运行的路径
在 macOS 上,Ollama 默认将模型存储在 ~/.ollama/models 目录。如果您希望更改模型的存储路径,可以通过设置环境变量 OLLAMA_MODELS 来实现。具体步骤如下: 选择新的模型存储目录:首先,确定您希望存储模型的目标目录路…...
1、http介绍
一、HTTP 和 HTTPS 简介 HTTP(HyperText Transfer Protocol) 用途:用于网页数据传输(不加密)。协议特性:以明文形式传输数据,默认端口 80,无身份验证和完整性保护。典型场景…...
