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

RT-Thread 操作系统 之 线程间同步 IO设备模型

RT-Thread 操作系统 之 线程间同步 IO设备模型

  • 一、线程间同步
    • 1.1、信号量
      • 1.1.1、信号量结构体
      • 1.1.2、信号量的使用和管理
      • 1.1.3、信号量同步例程
    • 1.2、互斥量
      • 1.2.1、互斥量的使用和管理
    • 1.3、事件集
      • 1.3.1、事件集使用和管理方法
      • 1.3.2、事件集三个线程同步实例
  • 二、IO设备模型
    • 2.1、IO设备类型
    • 2.2、创建和注册IO设备
    • 2.3、访问IO设备


一、线程间同步

多个执行单元(线程、中断)同时执行临界区,操作临界资源,会导致竟态产生,为了解决这种竟态问题,RT-Thread OS提供了如下几种同步互斥机制:
☐ 信号量
☐ 互斥量
☐ 事件集

1.1、信号量

信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步或互斥的目的。
每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当信号量实例数目为零时,再申请该信号量的线程就会被挂起在该信号量的等待队列上,等待可用的信号量实例(资源)

1.1.1、信号量结构体

struct rt_semaphore
{struct rt_ipc_object parent;  /**< inherit from ipc_object  继承自ipc_object类*/rt_uint16_t          value;       /**< value of semaphore. */rt_uint16_t          reserved;    /**< reserved field 预留*/ 
};
typedef struct rt_semaphore *rt_sem_t;

1.1.2、信号量的使用和管理

对一个信号量的操作包含:创建 / 初始化信号量、获取信号量、释放信号量、删除 / 脱离信号量。

在这里插入图片描述

☐ 创建和删除信号量
系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。
调用这个函数时,系统将删除这个信号量。如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是-RT_ERROR),然后再释放信号量的内存资源。

/*** This function will delete a semaphore object and release the memory** @param sem the semaphore object** @return the error code** @see rt_sem_detach*/
rt_err_t rt_sem_delete(rt_sem_t sem)

☐ 初始化和脱离信号量

/*** This function will initialize a semaphore and put it under control of* resource management.** @param sem the semaphore object* @param name the name of semaphore* @param value the initial value of semaphore* @param flag the flag of semaphore** @return the operation status, RT_EOK on successful*/
rt_err_t rt_sem_init(rt_sem_t    sem,const char *name,rt_uint32_t value,rt_uint8_t  flag)

脱离信号量就是让信号量对象从内核对象管理器中脱离,适用于静态初始化的信号量
使用该函数后,内核先唤醒所有挂在该信号量等待队列上的线程,然后将该信号量从内核对象管理器中脱离。原来挂起在信号量上的等待线程将获得 - RT_ERROR 的返回值。

/*** This function will detach a semaphore from resource management** @param sem the semaphore object** @return the operation status, RT_EOK on successful** @see rt_sem_delete*/
rt_err_t rt_sem_detach(rt_sem_t sem)

☐ 获取信号量
线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1,如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据time参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。如果在参数time指定的时间内依然得不到信号量,线程将超时返回,返回值是 - RT_ETIMEOUT。

☐ 释放信号量
释放信号量可以唤醒挂起在该信号量上的线程

/*** This function will release a semaphore, if there are threads suspended on* semaphore, it will be waked up.** @param sem the semaphore object** @return the error code*/
rt_err_t rt_sem_release(rt_sem_t sem)

1.1.3、信号量同步例程

在这里插入图片描述

1.2、互斥量

互斥量体现的是排他性,也是解决多线程同时操作临界区临界资源导致的竟态的一种方法。(类似于特殊的信号量——二值信号量)
区别:信号量可由不同线程释放,互斥量只能由同一线程进行释放。

1.2.1、互斥量的使用和管理

互斥量的操作包含:创建 / 初始化互斥量、获取互斥量、释放互斥量、删除 / 脱离互斥量

在这里插入图片描述

☐ 创建和删除
不再使用互斥量时,通过删除互斥量以释放系统资源,适用于动态创建的互斥量
当删除一个互斥量时,所有等待此互斥量的线程都将被唤醒,等待线程获得的返回值是

  • RT_ERROR
/*** This function will delete a mutex object and release the memory** @param mutex the mutex object** @return the error code** @see rt_mutex_detach*/
rt_err_t rt_mutex_delete(rt_mutex_t mutex)

☐ 初始化和脱离互斥量

/*** This function will initialize a mutex and put it under control of resource* management.** @param mutex the mutex object* @param name the name of mutex* @param flag the flag of mutex** @return the operation status, RT_EOK on successful*/
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)

使用该函数接口后,内核先唤醒所有挂在该互斥量上的线程(线程的返回值是
-RT_ERROR) ,然后系统将该互斥量从内核对象管理器中脱离。

/*** This function will detach a mutex from resource management** @param mutex the mutex object** @return the operation status, RT_EOK on successful** @see rt_mutex_delete*/
rt_err_t rt_mutex_detach(rt_mutex_t mutex)

☐ 获取互斥量

/*** This function will take a mutex, if the mutex is unavailable, the* thread shall wait for a specified time.** @param mutex the mutex object* @param time the waiting time** @return the error code*/
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)

☐ 释放互斥量

/*** This function will release a mutex, if there are threads suspended on mutex,* it will be waked up.** @param mutex the mutex object** @return the error code*/
rt_err_t rt_mutex_release(rt_mutex_t mutex)

1.3、事件集

事件集也是线程间同步的机制之一,一个事件集可以包含多个事件,利用事件集可以完成一对多,多对多的线程间同步。
一个线程和多个事件的关系可设置为:
其中任意一个事件唤醒 线程,或几个事件都到达后唤醒线程,多个事件集合可以用一个32bit无符号整型变量来表示,变量的每一位代表一个事件,线程通过"逻辑与"或"逻辑或"将一个或多个事件关联起来,形成事件组合。
RT-Thread 定义的事件集有以下特点:
☐ 事件只与线程相关,事件间相互独立
☐ 事件仅用于同步,不提供数据传输功能
☐ 事件无排队性,即多次向线程发送同一事件(如果线程还未来得及读走),其效果等同于只发送一次

在这里插入图片描述

1.3.1、事件集使用和管理方法

对一个事件集的操作包含:创建/初始化事件集、发送事件、接收事件、删除/脱离事件集。

在这里插入图片描述

☐ 创建和删除

/** event structure*/
struct rt_event
{struct rt_ipc_object parent;      /**< inherit from ipc_object */rt_uint32_t          set;         /**< event set */
};
typedef struct rt_event *rt_event_t;/*** This function will create an event object from system resource** @param name the name of event* @param flag the flag of event RT_IPC_FLAG_FIFO RT_IPC_FLAG_PRIO** @return the created event, RT_NULL on error happen*/
rt_event_t rt_event_create(const char *name, rt_uint8_t flag)/*** This function will delete an event object and release the memory** @param event the event object** @return the error code*/
rt_err_t rt_event_delete(rt_event_t event)

☐ 初始化和脱离

/*** This function will initialize an event and put it under control of resource* management.** @param event the event object* @param name the name of event* @param flag the flag of event** @return the operation status, RT_EOK on successful*/
rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag)/*** This function will detach an event object from resource management** @param event the event object** @return the operation status, RT_EOK on successful*/
rt_err_t rt_event_detach(rt_event_t event)

☐ 发送事件

/*** This function will send an event to the event object, if there are threads* suspended on event object, it will be waked up.** @param event the event object* @param set the event set** @return the error code*/
rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)

☐ 接收事件

/*** This function will receive an event from event object, if the event is* unavailable, the thread shall wait for a specified time.** @param event the fast event object* @param set the interested event set* @param option the receive option, either RT_EVENT_FLAG_AND or*        RT_EVENT_FLAG_OR should be set. RT_EVENT_FLAG_CLEAR * @param timeout the waiting time  RT_WAITING_FOREVER RT_WAITING_NO* @param recved the received event, if you don't care, RT_NULL can be set.** @return the error code*/
rt_err_t rt_event_recv(rt_event_t   event,rt_uint32_t  set,rt_uint8_t   option,rt_int32_t   timeout,rt_uint32_t *recved)

1.3.2、事件集三个线程同步实例

见源码

在这里插入图片描述

二、IO设备模型

RT-Thread 提供了一套简单的 I/O 设备模型框架,如下图所示,它位于硬件和应用程序之间,共分成三层,从上到下分别是 I/O 设备管理层、设备驱动框架层、设备驱动层。

在这里插入图片描述

☐ 应用程序通过 I/O 设备管理接口获得正确的设备驱动,然后通过这个设备驱动与底层 I/O 硬件设备进行交互。
☐ I/O 设备管理层实现了对设备驱动程序的封装
☐ 设备驱动框架层是对同类硬件设备驱动的抽象,将不同厂家的同类硬件设备驱动中相同的部分抽取出来,将不同部分留出接口,由驱动程序实现。
☐ 设备驱动层是一组驱使硬件设备工作的程序,实现访问硬件设备的功能。

简单设备的注册不经过设备驱动框架层,直接将设备注册到I/O设备管理器中
☐ 设备驱动根据设备模型定义,创建出具备硬件访问能力的设备实例,将该设备通过rt_device_register()接口注册到 I/O 设备管理器中
☐ 应用程序通过 rt_device_find()接口查找到设备,然后使用 I/O 设备管理接口来访问硬件,如下图所示:

在这里插入图片描述

对于一些复杂设备,需要使用到对应的设备驱动框架层,进行注册,如:看门狗定时器
☐ 看门狗设备驱动程序根据看门狗设备模型定义,创建出具备硬件访问能力的看门狗设备实例,并将该看门狗设备通过 rt_hw_watchdog_register()接口注册到看门狗设备驱动框架中
☐ 看门狗设备驱动框架通过 rt_device_register()接口将看门狗设备注册到 I/O 设备管理器中
☐ 应用程序通过 I/O 设备管理接口来访问看门狗设备硬件

在这里插入图片描述

2.1、IO设备类型

☐ RT-Thread 支持多种 I/O 设备类型,主要设备类型如下所示

RT_Device_Class_Char = 0,                           /**< character device */     RT_Device_Class_Block,                              /**< block device */     RT_Device_Class_NetIf,                              /**< net interface */     RT_Device_Class_MTD,                                /**< memory device */     RT_Device_Class_CAN,                                /**< CAN device */     RT_Device_Class_RTC,                                /**< RTC device */     RT_Device_Class_Sound,                              /**< Sound device */     RT_Device_Class_Graphic,                            /**< Graphic device */     RT_Device_Class_I2CBUS,                             /**< I2C bus device */     RT_Device_Class_USBDevice,                          /**< USB slave device */     RT_Device_Class_USBHost,                            /**< USB host bus */     RT_Device_Class_SPIBUS,                             /**< SPI bus device */     RT_Device_Class_SPIDevice,                          /**< SPI device */     RT_Device_Class_SDIO,                               /**< SDIO bus device */        RT_Device_Class_Timer,                              /**< Timer device */     RT_Device_Class_Miscellaneous,                      /**< misc device */     RT_Device_Class_Sensor,                             /**< Sensor device */     RT_Device_Class_Touch,                              /**< Touch device */     RT_Device_Class_Unknown                             /**< unknown device */ 

2.2、创建和注册IO设备

☐ 驱动层负责创建设备实例,并注册到 I/O 设备管理器中

当一个动态创建的设备不再需要使用时可以通过如下函数来销毁

☐设备被创建后,需要实现它访问硬件的操作方法

☐ 设备被创建后,需要注册到 I/O 设备管理器中,应用程序才能够访问

/*** This function registers a device driver with specified name.** @param dev the pointer of device driver structure* @param name the device driver's name* @param flags the capabilities flag of device   设备模式标志** @return the error code, RT_EOK on initialization successfully.*/
rt_err_t rt_device_register(rt_device_t dev,const char *name,rt_uint16_t flags)
                           
#define RT_DEVICE_FLAG_RDONLY 0x001 /*只读*/
#define RT_DEVICE_FLAG_WRONLY 0x002 /*只写*/
#define RT_DEVICE_FLAG_RDWR 0x003 /*读写*/
#define RT_DEVICE_FLAG_REMOVABLE 0x004 /*可移除*/
#define RT_DEVICE_FLAG_STANDALONE 0x008 /*独立*/
#define RT_DEVICE_FLAG_SUSPENDED 0x020 /*挂起*/
#define RT_DEVICE_FLAG_STREAM 0x040 /*流模式*/
#define RT_DEVICE_FLAG_INT_RX 0x100 /*中断接收*/
#define RT_DEVICE_FLAG_DMA_RX 0x200 /*DMA接收*/
#define RT_DEVICE_FLAG_INT_TX 0x400 /*中断发送*/
#define RT_DEVICE_FLAG_DMA_TX 0x800 /* DMA发送*/

设备注销后的,设备将从设备管理器中移除,也就不能再通过设备查找搜索到该设备。注销设备不会释放设备控制块占用的内存

/*** This function removes a previously registered device driver** @param dev the pointer of device driver structure** @return the error code, RT_EOK on successfully.*/
rt_err_t rt_device_unregister(rt_device_t dev)

2.3、访问IO设备

应用程序通过 I/O 设备管理接口来访问硬件设备,当设备驱动实现后,应用程序就可以访问该硬件,I/O 设备管理接口与 I/O 设备的操作方法的映射关系下图所示

在这里插入图片描述

☐ 查找设备

/*** This function finds a device driver by specified name.** @param name the device driver's name** @return the registered device driver on successful, or RT_NULL on failure.*/
rt_device_t rt_device_find(const char *name)

☐ 初始化设备

☐ 打开和关闭设备

注:RT_DEVICE_FLAG_STREAM:流模式用于向串口终端输出字符串:当输出的字符是 “\n”(对应 16 进制值为 0x0A)时,自动在前面输出一个 “\r”(对应 16 进制值为 0x0D)做分行。
流模式 RT_DEVICE_FLAG_STREAM 可以和接收发送模式参数使用或 “|” 运算符一起使用

☐ 控制设备

☐ 读写设备

/*** This function will read some data from a device.** @param dev the pointer of device driver structure* @param pos the position of reading* @param buffer the data buffer to save read data* @param size the size of buffer** @return the actually read size on successful, otherwise negative returned.** @note since 0.4.0, the unit of size/pos is a block for block device.*/
rt_size_t rt_device_read(rt_device_t dev,rt_off_t    pos,void       *buffer,rt_size_t   size)/*** This function will write some data to a device.** @param dev the pointer of device driver structure* @param pos the position of written* @param buffer the data buffer to be written to device* @param size the size of buffer** @return the actually written size on successful, otherwise negative returned.** @note since 0.4.0, the unit of size/pos is a block for block device.*/
rt_size_t rt_device_write(rt_device_t dev,rt_off_t    pos,const void *buffer,rt_size_t   size)

☐ 数据收发回调,当硬件设备收到数据时,可以通过如下函数回调另一个函数来设置数据接收指示,通知上层应用线程有数据到达

/*** This function will set the reception indication callback function. * This callback function* is invoked when this device receives data.** @param dev the pointer of device driver structure* @param rx_ind the indication callback function** @return RT_EOK*/
rt_err_t
rt_device_set_rx_indicate(rt_device_t dev,rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size))/*** This function will set the indication callback function when device has* written data to physical hardware.** @param dev the pointer of device driver structure* @param tx_done the indication callback function** @return RT_EOK*/
rt_err_t
rt_device_set_tx_complete(rt_device_t dev,rt_err_t (*tx_done)(rt_device_t dev, void *buffer))

相关文章:

RT-Thread 操作系统 之 线程间同步 IO设备模型

RT-Thread 操作系统 之 线程间同步 IO设备模型 一、线程间同步1.1、信号量1.1.1、信号量结构体1.1.2、信号量的使用和管理1.1.3、信号量同步例程 1.2、互斥量1.2.1、互斥量的使用和管理 1.3、事件集1.3.1、事件集使用和管理方法1.3.2、事件集三个线程同步实例 二、IO设备模型2.…...

力扣leetcode移动0(C++)

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: […...

阿里云部署open-webui实现openai代理服务

一、 环境准备 1. 阿里云服务器&#xff0c;ubuntu22系统 2. 外网服务器&#xff0c;linux系统 3. openai API Key 二、实际操作记录(阿里云服务器端) 1. 根据官方文档安装open-webui服务端: &#x1f680; Getting Started | Open WebUI 1. 如果服务器配置比较低&#xff0c;…...

你的工作环境,选对劳保鞋了吗?守护安全,从脚下开始!

在众多的工作场所中&#xff0c;我们穿梭于不同的工作环境&#xff0c;从繁忙的工厂车间到复杂的建筑工地&#xff0c;再到需要精细操作的实验室……每一步都承载着对安全的期许和对效率的追求。但你是否意识到&#xff0c;脚下那双不起眼的劳保鞋&#xff0c;其实是守护你安全…...

【Linux】编译器gcc/g++ 、程序翻译过程、动静态库

目录 1.gcc/g Linux编译器1.1. gcc与g的安装1.2. gcc与g用法1.2.1.gcc用法1.2.2. g用法 1.3. 程序翻译的过程1.3.1. 前提知识&#xff1a;1.3.2. 预处理&#xff08;语言种类不变&#xff09;条件编译用途&#xff1a; 1.3.3. 编译&#xff08;生成汇编语言&#xff09;1.3.4. …...

通义灵码-阿里云推出的AI智能编码助手

通义灵码体验地址 标题通义灵码是什么&#xff1f; 通义灵码是由阿里巴巴推出的基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研发智能问答、异常报错排查等能力&#xff0c;并针对阿里云…...

构建智能生态,视频监控/安防监控EasyCVR视频汇聚流媒体技术在智能分析领域的应用

随着5G、AI、物联网&#xff08;IoT&#xff09;、云计算等技术的快速发展&#xff0c;万物互联的时代已经到来&#xff0c;全新的行业生态AIoT正在引领一场深刻的变革。在这场变革中&#xff0c;EasyCVR视频流媒体技术以其强大的视频处理、汇聚与融合能力&#xff0c;在智能分…...

LeetCode Hard|【460. LFU 缓存】

力扣题目链接 LFU全称是最不经常使用算法&#xff08;Least Frequently Used&#xff09;&#xff0c;LFU算法的基本思想和所有的缓存算法一样&#xff0c;一定时期内被访问次数最少的页&#xff0c;在将来被访问到的几率也是最小的。 相较于 LRU 算法&#xff0c;LFU 更加注重…...

积极参与全球能源科技前沿对话,海博思创推动绿色低碳发展

在能源转型与绿色低碳发展的全球浪潮中&#xff0c;国内领先的储能解决方案供应商海博思创以卓越的技术实力和前瞻性的战略眼光&#xff0c;站在了行业变革的前沿。公司不仅在国内外多个重要展会上大放异彩&#xff0c;更通过一系列技术创新与深度合作&#xff0c;为全球能源行…...

[工具]-ffmpeg-笔记

朋友有一个需求&#xff0c;将视频文件转化为音频文件、音频文件获取音频转化为文本文件。 思路&#xff1a;通过ffmpeg转化视频为音频&#xff0c;通过百度ai提供的voice_t_text接口提取语音文本&#xff0c;但是需要将音频分割成1分钟内的pcm编码 &#xff0c;采样率16000的…...

Android Fragment:详解,结合真实开发场景Navigation

目录 1&#xff09;Fragment是什么 2&#xff09;Fragment的应用场景 3&#xff09;为什么使用Fragment? 4&#xff09;Fragment如何使用 5&#xff09;Fragment的生命周期 6&#xff09;Android开发&#xff0c;建议是多个activity&#xff0c;还是activity结合fragment&…...

JavaWeb中的Servlet

本笔记基于【尚硅谷全新JavaWeb教程&#xff0c;企业主流javaweb技术栈】https://www.bilibili.com/video/BV1UN411x7xe?vd_sourcea91dafe0f846ad7bd19625e392cf76d8总结 Servlet Servlet简介 动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运…...

SpringBoot AOP 简单的权限校验

本篇文章的主要内容是通过AOP切面编程实现简单的权限校验。 书接上回登录与注册功能 我们的用户表里面不是有role(权限)这个字段吗 在JWT令牌的生成中&#xff0c;我们加入了role字段。 那么接下来&#xff0c;我们就可以通过这个字段来实现权限校验。 我这里就很简单&#x…...

Java生成Word->PDF->图片:基于poi-tl 进行word模板渲染

文章目录 引言I Java生成Word、PDF、图片文档获取标签渲染数据生成文档案例II 工具类封装2.1 word 渲染和word 转 pfd2.2 pdf转成一张图片III poi-tl(word模板渲染) 标签简介文本标签{{var}}图片标签表格标签引用标签IV poi-tl提供了类 Configure 来配置常用的设置标签类型前后…...

JVM内存模型笔记

1. 运行时数据区概述 JVM内存布局规定了Java运行过程中的内存申请、分配和管理策略。运行时数据区分为线程私有和线程共享两种。 2. 线程私有内存 程序计数器&#xff1a;存储当前线程执行的字节码指令地址。虚拟机栈&#xff1a;保存方法调用的局部变量和部分结果。本地方法…...

每日一练 - eSight 网管远程告警通知方式

01 真题题目 eSight 网管支持的远程告警通知方式包括:(多选) A.邮件 B.语音 C.短信 D.微信 02 真题答案 AC 03 答案解析 eSight 网管系统支持多种远程告警通知方式&#xff0c;包括邮件和短信。 这些通知方式可以帮助网络管理员及时了解网络设备的状态和告警信息&#xff0…...

[matlab] 鲸鱼优化算法优化KNN分类器的特征选择

目录 引言 智能优化算法概述 智能优化算法在KNN特征选择中的应用 应用步骤 UCI数据集 鲸鱼优化算法 一、算法背景与原理 二、算法组成与步骤 三、算法特点与优势 四、应用与挑战 代码实现 鲸鱼优化算法 主程序 打印结果 引言 智能优化算法在优化KNN&#xff08;…...

vscode ssh-remote 疑似内存泄漏问题

vscode ssh-remote疑似内存泄漏问题 系统信息与版本号 版本&#xff1a;1.88.1&#xff08;通用&#xff09; 日期&#xff1a;2024-04-10T17:42:52.765Z Electron: 28.2.8 ElectronBuildId: 27744544 Chromium&#xff1a;120.0.6099.291 Node.js&#xff1a;18.18.2 V8&…...

初识自然语言处理NLP

文章目录 1、简介2、自然语言处理的发展简史3、语言学理论句法学&#xff08;Syntax&#xff09;语义学&#xff08;Semantics&#xff09;语用学&#xff08;Pragmatics&#xff09;形态学&#xff08;Morphology&#xff09; 4、统计与机器学习方法n-gram 模型隐马尔可夫模型…...

分布式系统架构-微服务架构

一.什么是分布式系统架构 分布式系统架构是指将一个单一的应用程序或服务拆分成多个独立的部分&#xff0c;这些部分可以在不同的计算机、服务器或者地理位置上运行&#xff0c;并通过网络进行通信和协作。分布式系统的设计旨在提高系统的可靠性、可用性和扩展性&#xff0c;同…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...

从零开始了解数据采集(二十八)——制造业数字孪生

近年来&#xff0c;我国的工业领域正经历一场前所未有的数字化变革&#xff0c;从“双碳目标”到工业互联网平台的推广&#xff0c;国家政策和市场需求共同推动了制造业的升级。在这场变革中&#xff0c;数字孪生技术成为备受关注的关键工具&#xff0c;它不仅让企业“看见”设…...