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

Linux驱动如何向应用层提供sysfs操作接口

在 Linux 中,用户态操作驱动设备主要有以下 5 种方式,每种方式适用于不同的场景,各有其特点和用途:

1. 字符设备(Char Device)接口

这是最常用的设备交互方式,适用于流式数据传输复杂命令交互的设备(如串口、LED、传感器、显卡等)。

核心特点:

  • 通过 /dev 目录下的设备节点(如 /dev/ttyS0/dev/led0)操作;
  • 驱动需实现 file_operations 结构体(open/read/write/ioctl 等);
  • 支持阻塞 / 非阻塞读写、ioctl 命令控制、mmap 内存映射等复杂操作。

示例(用户态代码):

// 打开设备
int fd = open("/dev/led0", O_RDWR);
if (fd < 0) { /* 错误处理 */ }// 写入数据(如控制 LED 亮度)
write(fd, "255", 3);// 发送命令(如通过 ioctl 设置模式)
ioctl(fd, LED_SET_MODE, MODE_BLINK);// 关闭设备
close(fd);

适用场景:

需要复杂交互(如命令控制、批量数据传输、异步操作)的设备。

2. sysfs 接口

基于虚拟文件系统的属性暴露机制,适用于简单的属性读写(如设备状态查询、参数配置)。

核心特点:

  • 通过 /sys 目录下的属性文件(如 /sys/class/leds/led0/brightness)操作;
  • 驱动只需定义 show/store 回调函数(无需完整 file_operations);
  • 接口标准化,操作简单(通过 cat/echo 即可交互)。

示例(用户态操作):

# 读取亮度
cat /sys/class/leds/led0/brightness# 设置亮度
echo 255 > /sys/class/leds/led0/brightness

适用场景:

简单的属性配置(如开关、亮度、模式切换),无需复杂命令交互的设备。

3. procfs 接口

基于 /proc 虚拟文件系统,主要用于内核 / 驱动的状态信息查询(如进程状态、内存使用、驱动调试信息)。

核心特点:

  • 通过 /proc 目录下的文件(如 /proc/cpuinfo/proc/driver/mydriver)操作;
  • 驱动需注册 proc_ops 结构体(类似 file_operations);
  • 更偏向 “信息展示”,而非设备控制(现代驱动中逐渐被 sysfs 替代)。

示例(用户态操作):

# 查看驱动调试信息
cat /proc/driver/mydriver/debug_info

适用场景:

内核 / 驱动的调试信息输出、系统状态查询(如 /proc/net 网络信息)。

4. 设备文件系统(devfs)

早期 Linux 用于管理设备节点的文件系统,现已被 udev + devtmpfs 替代,但概念上仍需了解。

核心特点:

  • 自动创建 /dev 节点,无需手动 mknod
  • 现代系统中,udev 会根据设备的 subsystemdevtype 等属性动态生成 /dev 节点,并支持规则自定义(如 /etc/udev/rules.d/)。

示例(udev 规则自定义节点名称):

# /etc/udev/rules.d/70-led.rules
SUBSYSTEM=="leds", ATTR{name}=="user-led", SYMLINK+="myled"
# 生成 /dev/myled 符号链接,指向实际 LED 设备节点

适用场景:

设备节点的动态管理和命名规则自定义。

5. Netlink 套接字

基于内核与用户态的异步通信机制,适用于事件通知高频数据交互(如热插拔事件、网络配置、实时监控)。

核心特点:

  • 类似 socket 接口,支持双向通信和多播;
  • 驱动需注册 netlink_kernel_cfg 结构体,用户态通过 socket API 操作;
  • 效率高于 ioctl,适合传递结构化数据和异步事件。

示例(用户态代码框架):

// 创建 netlink 套接字
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_MYDRIVER);
// 绑定地址、发送/接收数据...

适用场景:

设备事件通知(如热插拔、状态变化)、内核与用户态的高频数据交换。

总结:选择原则

交互需求推荐方式典型设备 / 场景
复杂命令 / 流式数据字符设备(/dev串口、显卡、传感器数据采集
简单属性读写sysfs(/sysLED 亮度、温度传感器数值
调试信息 / 系统状态procfs(/proc内核版本、驱动调试日志
设备节点动态管理udev + devtmpfs自动生成 / 命名 /dev 节点
异步事件 / 高频通信Netlink 套接字热插拔事件、实时监控数据

实际开发中,常结合多种方式(如字符设备 + sysfs:/dev 用于数据传输,/sys 用于参数配置)。

本文我们主要讲解sysfs接口。。。。。。。。。。。。。。。

主要目录文件

Linux 内核中 sysfs 的实现涉及多个核心目录和文件,这些文件分布在内核源码的不同路径下,共同构成了 sysfs 虚拟文件系统的框架、属性管理和与其他子系统的交互逻辑。以下是核心的实现目录和文件及其作用:

一、sysfs 核心实现目录

sysfs 的核心代码集中在 fs/sysfs/ 目录下,该目录包含了 sysfs 文件系统的底层实现(如 inode 管理、文件操作、目录结构维护等)。

二、核心文件及功能说明

1. fs/sysfs/file.c

  • 作用:实现 sysfs 中文件的核心操作逻辑,是 sysfs 与 VFS(虚拟文件系统)对接的关键。
  • 核心内容
    • 定义 sysfs 的 file_operations 结构体(sysfs_file_operations),包含 open/read/write/llseek 等通用文件操作;
    • 实现用户空间与内核空间的数据交互(如 sysfs_read/sysfs_write 函数,负责将用户读写转发给属性的 show/store 回调);
    • 管理文件的打开 / 关闭状态,处理并发访问。

2. fs/sysfs/dir.c

  • 作用:管理 sysfs 的目录结构,负责目录的创建、删除和层级关系维护。
  • 核心内容
    • 定义 sysfs_dirent 结构体(sysfs 中目录和文件的统一表示,包含名称、类型、父节点指针等);
    • 实现目录创建(sysfs_create_dir)、删除(sysfs_remove_dir)、重命名等操作;
    • 维护 sysfs 的目录树结构,确保节点间的层级关系正确。

3. fs/sysfs/sysfs.h

  • 作用sysfs 内部的头文件,定义核心数据结构和内部函数声明。
  • 核心内容
    • 声明 struct sysfs_direntstruct sysfs_ops 等核心结构体;
    • 定义 sysfs 内部使用的宏和辅助函数(如 sysfs_get/sysfs_put 用于引用计数管理)。

4. fs/sysfs/attr.c

  • 作用:处理 sysfs 属性(attribute)的注册与管理,是驱动与 sysfs 交互的桥梁。
  • 核心内容
    • 实现属性文件的创建(sysfs_create_file)、删除(sysfs_remove_file);
    • 处理属性组(attribute group)的批量注册(sysfs_create_group);
    • 关联属性的 show/store 回调函数与 sysfs 的文件操作。

5. fs/sysfs/mount.c

  • 作用:负责 sysfs 文件系统的挂载初始化,是 sysfs 作为虚拟文件系统的入口。
  • 核心内容
    • 定义 sysfs 的 file_system_type 结构体(sysfs_fs_type),向 VFS 注册 sysfs
    • 实现 sysfs 的挂载函数(sysfs_mount),初始化根目录和超级块(super block)。

三、与其他子系统的交互文件

sysfs 并非独立存在,而是与内核其他子系统(如设备模型、总线、驱动)深度集成,这些子系统通过特定文件定义自己的 sysfs 属性:

1. 设备模型相关(include/linux/device.h

  • 定义 struct device_attribute(设备属性结构体)和 DEVICE_ATTR 宏,用于设备在 sysfs 中暴露属性;
  • 提供 device_create_file/device_remove_file 等函数,简化设备属性的注册。

2. 总线与驱动相关(include/linux/device.hinclude/linux/module.h

  • 总线(如 platform 总线)和驱动通过 struct bus_attributestruct driver_attribute 定义自己的 sysfs 属性;
  • 例如,/sys/bus/platform/drivers/ 下的驱动属性文件,由 driver_create_file 函数创建。

3. 类设备相关(include/linux/device.h

  • 类(struct class)通过 struct class_attribute 定义类级别的 sysfs 属性(如 /sys/class/leds/ 目录下的共性属性);
  • 提供 class_create_file 等函数,用于类属性的注册。

四、用户态可见的 sysfs 目录结构

虽然不属于内核实现文件,但了解用户态可见的 sysfs 目录结构有助于理解其实现逻辑。sysfs 挂载在 /sys 目录下,核心子目录包括:

  • /sys/devices/:所有设备的底层表示,按硬件拓扑结构组织;
  • /sys/class/:按设备功能分类的目录(如 ledsttynet),是用户访问的主要入口;
  • /sys/bus/:按总线类型分类(如 platformusb),包含总线上的设备和驱动;
  • /sys/drivers/:系统中所有驱动的信息;
  • /sys/dev/:设备号与设备的映射关系。

总结

sysfs 的实现以 fs/sysfs/ 目录为核心,其中 file.cdir.cattr.c 分别负责文件操作、目录管理和属性注册,mount.c 负责与 VFS 对接。同时,内核其他子系统(设备模型、总线、驱动)通过定义属性结构体和注册函数,将自身信息暴露到 sysfs 中,最终形成用户态可见的 /sys 目录结构。这些文件共同实现了 sysfs 作为 “内核对象属性暴露机制” 的核心功能。

如何生成sysfs接口

在 Linux 驱动中,向用户空间提供 sysfs 操作接口的核心是定义 “属性(attribute)” 并注册到内核,通过内核提供的标准化接口将属性文件暴露在 /sys 目录下。以下是具体实现步骤和示例:

一、核心概念:sysfs 属性(attribute)

sysfs 接口的基本单位是 “属性文件”(如 /sys/class/leds/led0/brightness),每个属性文件对应一个 struct attribute 或其派生结构体(如设备属性 struct device_attribute),包含:

  • 属性名称(如 "brightness");
  • 访问权限(如 0644 表示用户可读、root 可写);
  • 读写回调函数(用户读写文件时触发,实现具体逻辑)。

二、驱动实现 sysfs 接口的步骤

1. 包含必要头文件

#include <linux/sysfs.h>       // sysfs 核心定义
#include <linux/kobject.h>     // kobject 相关(sysfs 依赖的对象模型)
#include <linux/device.h>      // 设备属性相关(如 struct device_attribute)

2. 定义属性读写回调函数

回调函数是 sysfs 接口的核心,负责处理用户空间的读写请求:

  • 读函数(show:用户执行 cat 时调用,将内核数据返回给用户;
  • 写函数(store:用户执行 echo 时调用,处理用户传入的数据。

示例(以 LED 亮度控制为例)

// 读回调:返回当前亮度
static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf) {struct my_led_dev *led_dev = dev_get_drvdata(dev);  // 获取私有数据// 将亮度值写入 buf,返回字符串长度(内核会自动将 buf 复制到用户空间)return sprintf(buf, "%d\n", led_dev->brightness);
}// 写回调:设置亮度(并控制硬件)
static ssize_t brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {struct my_led_dev *led_dev = dev_get_drvdata(dev);unsigned int brightness;int ret;// 将用户传入的字符串(如 "255")转换为整数ret = kstrtouint(buf, 10, &brightness);if (ret < 0)return ret;// 校验亮度范围(0~255)if (brightness > 255)return -EINVAL;// 更新私有数据led_dev->brightness = brightness;// 控制硬件(如通过 GPIO 点亮/熄灭 LED)gpiod_set_value(led_dev->gpiod, brightness ? 1 : 0);return count;  // 返回处理的字节数
}

3. 定义属性结构体

通过内核提供的宏(如 DEVICE_ATTR)将属性名称、权限和回调函数绑定:

// 定义名为 "brightness" 的设备属性,权限 0644(可读可写)
static DEVICE_ATTR(brightness, 0644, brightness_show, brightness_store);
  • DEVICE_ATTR 是设备类属性的宏,展开后生成 struct device_attribute 结构体;
  • 格式:DEVICE_ATTR(属性名, 权限, 读函数, 写函数)
  • 权限规则同文件系统(如 0644 表示 rw-r--r--)。

4. 注册属性到 sysfs

将定义的属性添加到内核的 sysfs 目录中,通常在驱动的 probe 函数中完成:

  • device_create_file(dev, &dev_attr_brightness):在设备的 sysfs 目录(如 /sys/devices/platform/.../)下创建 brightness 文件;
  • 若要创建多个属性,可多次调用 device_create_file,或使用 device_create_files 批量注册。

5. 注销属性(可选)

驱动卸载时,需清理 sysfs 属性(通常在 remove 函数中):

static int my_led_remove(struct platform_device *pdev) {struct device *dev = &pdev->dev;// 注销属性文件device_remove_file(dev, &dev_attr_brightness);return 0;
}

三、sysfs 目录的组织方式

sysfs 接口的路径由驱动注册时的 “对象类型” 决定,常见场景:

  1. 设备相关属性:注册到设备的 sysfs 目录(/sys/devices/.../,由内核自动生成);
  2. 类设备属性:若驱动使用 class_create 创建了类(如 LED 子系统的 leds 类),属性会出现在 /sys/class/<类名>/<设备名>/ 下(更易访问);
    // 示例:创建类并关联设备,属性会出现在 /sys/class/my_led_class/led0/ 下
    struct class *my_led_class = class_create(THIS_MODULE, "my_led_class");
    device_create(my_led_class, NULL, devno, NULL, "led0");  // 生成 /sys/class/my_led_class/led0/
    
  3. 总线 / 驱动属性:注册到总线或驱动的目录(如 /sys/bus/platform/drivers/my_led/)。

四、用户空间操作示例

属性注册成功后,用户可通过标准文件操作接口访问:

# 查看当前亮度
cat /sys/class/my_led_class/led0/brightness# 设置亮度为 255(点亮)
echo 255 > /sys/class/my_led_class/led0/brightness# 设置亮度为 0(熄灭)
echo 0 > /sys/class/my_led_class/led0/brightness

五、高级用法:属性组(attribute group)

若驱动需要暴露多个属性(如 brightnesstriggerdelay_on),可将其组织为 “属性组” 批量注册,简化代码:

// 定义多个属性
static DEVICE_ATTR(brightness, 0644, brightness_show, brightness_store);
static DEVICE_ATTR(trigger, 0644, trigger_show, trigger_store);// 定义属性组
static struct attribute *my_led_attrs[] = {&dev_attr_brightness.attr,&dev_attr_trigger.attr,NULL  // 数组结尾必须为 NULL
};
ATTRIBUTE_GROUPS(my_led);  // 生成属性组结构体// 注册属性组(在 probe 中)
ret = device_add_groups(dev, my_led_groups);

总结

Linux 驱动向用户提供 sysfs 接口的核心流程是:

  1. 实现属性的 show(读)和 store(写)回调函数;
  2. 用 DEVICE_ATTR 等宏定义属性结构体;
  3. 通过 device_create_file 或属性组将属性注册到 sysfs;
  4. 用户空间通过 /sys 目录下的属性文件与驱动交互。

这种方式无需手动实现 file_operations,内核会自动处理文件系统交互细节,是驱动向用户空间暴露简单控制接口的首选方式。

主要应用场景

sysfs 确实更适合实现简单的属性读写操作,但通过合理设计,也能支持一定程度的复杂交互。不过受限于其 “属性文件” 的设计理念,它在复杂操作场景下存在明显局限性。

一、sysfs 的设计定位:聚焦 “属性暴露”

sysfs 诞生的核心目标是将内核对象(如设备、驱动、总线)的属性以文件形式暴露给用户空间,方便用户查询和配置这些属性(如设备状态、硬件参数、驱动配置等)。

其设计理念决定了它天然适合:

  • 简单的键值对式属性(如 brightness = 255temperature = 35);
  • 单次读写即可完成的操作(如开关设备、修改参数);
  • 无需复杂状态交互的场景(如查询设备版本、查看资源占用)。

二、sysfs 能支持的 “非简单” 操作(有限)

通过一些技巧,sysfs 可以实现略复杂的交互,但本质上仍是基于 “文件读写” 的扩展:

1. 多值属性(结构化数据)

可以在一个属性文件中读写结构化数据(如逗号分隔的多个参数),在 show/store 函数中解析。
例如,一个控制 LED 闪烁的属性 blink_params

// 写回调:解析 "on_ms,off_ms" 格式的参数
static ssize_t blink_params_store(...) {unsigned int on_ms, off_ms;// 从 buf 中解析两个数值(如 "500,300")if (sscanf(buf, "%u,%u", &on_ms, &off_ms) != 2)return -EINVAL;// 配置硬件闪烁参数set_led_blink(on_ms, off_ms);return count;
}
// 读回调:返回当前闪烁参数
static ssize_t blink_params_show(...) {return sprintf(buf, "%u,%u\n", led_dev->on_ms, led_dev->off_ms);
}
DEVICE_ATTR(blink_params, 0644, blink_params_show, blink_params_store);

用户操作:

echo "500,300" > /sys/class/leds/led0/blink_params  # 设置亮500ms,灭300ms

2. 触发式操作(无数据交互)

通过 “空文件” 触发操作(写入任意内容即执行动作,无需传递参数)。
例如,一个重启设备的属性 reset

static ssize_t reset_store(...) {// 忽略写入内容,直接执行重启逻辑device_reset(dev);return count;
}
// 只读为空,只需要写回调
DEVICE_ATTR(reset, 0200, NULL, reset_store);  # 权限 0200 表示仅 root 可写

用户操作:

echo 1 > /sys/class/mydevice/reset  # 触发设备重启(写入任意内容均可)

3. 批量属性(属性组)

通过属性组(attribute group)将多个相关属性组织在一起,形成 “逻辑上的复杂接口”。
例如,一个传感器设备可能有 temperaturehumiditypressure 三个属性,用户可分别读写,组合起来实现环境监测。

三、sysfs 的局限性(不适合复杂操作)

尽管能做一些扩展,sysfs 仍有难以突破的限制,使其不适合复杂交互:

1. 没有 “命令” 概念,仅支持 “属性读写”

sysfs 本质是 “文件”,只能通过 read/write 操作,无法像 ioctl 那样传递 “命令 + 参数”(如 IOCTL_SET_MODE(MODE_FAST))。复杂操作需要拆解为多个属性,或在 store 中解析字符串命令(如 echo "set_mode fast" > control),可读性和效率都很差。

2. 不支持双向流交互

无法像字符设备那样通过 read/write 实现 “持续数据流”(如串口收发数据)。sysfs 的 read 通常是 “一次性返回当前状态”,而非 “阻塞等待新数据”。

3. 缺乏并发控制和事务性

  • 多个属性的读写无法保证原子性(如同时修改 on_ms 和 off_ms 可能导致中间状态异常);
  • 内核对 sysfs 的并发访问控制有限,复杂场景下需驱动自行实现锁机制,容易出错。

4. 性能限制

sysfs 每次读写都会涉及用户态 / 内核态切换,且文件操作本身有开销,不适合高频交互(如每秒数千次的参数修改)。

四、复杂操作该用什么?

如果需要复杂交互,应选择更适合的用户空间接口:

交互类型推荐接口典型场景
命令 + 参数(如配置模式)字符设备(ioctl摄像头参数配置、网络设备控制
持续数据流(如收发数据)字符设备 / 块设备(read/write串口通信、磁盘读写、音频流
高频数据交互共享内存(mmap)+ 字符设备显卡驱动、高性能传感器数据采集
异步事件通知netlink 或 uevent热插拔事件、设备状态变化通知

总结

sysfs 的核心定位是 **“属性暴露与简单配置”**,最适合实现键值对式的属性读写。虽然通过技巧能支持一定的复杂操作(如结构化数据、触发式动作),但受限于其 “文件属性” 的设计理念,在命令交互、流数据、并发控制等场景下存在天然缺陷。

驱动开发中应遵循 “简单属性用 sysfs,复杂交互用字符设备 / 其他接口” 的原则,避免过度使用 sysfs 实现不适合的功能。

sysfs和设备节点

sysfs也是基于file_operations,难道不会同时生成设备节点文件吗?

sysfs 虽然基于 file_operations,但它不会生成 /dev 目录下的设备节点文件,这与它的设计定位和内核实现方式密切相关。核心原因是:sysfs 是一种 “虚拟文件系统”,其文件是内核动态创建的 “属性节点”,而非传统意义上的 “设备节点”

1. 先明确两个概念的区别

  • /dev 下的设备节点:通常是字符设备、块设备等 “可操作设备” 的入口,由 mknod 或内核 device_create() 生成,关联具体的设备驱动(通过主 / 次设备号绑定 file_operations),用于复杂的设备交互(如 read/write/ioctl)。
  • sysfs 下的属性文件:是内核对象(设备、驱动、总线等)的 “属性描述”,由内核在 sysfs 文件系统中动态创建,仅用于暴露属性(如状态、参数),不关联主 / 次设备号。

2. sysfs 基于 file_operations,但为何不生成 /dev 节点?

(1)file_operations 的作用不同

sysfs 的 file_operations 是内核为 sysfs 虚拟文件系统实现的通用模板(定义在 fs/sysfs/file.c 中),其核心作用是:

  • 处理用户对 sysfs 属性文件的 read/write 操作;
  • 将操作转发给驱动定义的 show/store 回调函数(属性读写逻辑)。

而 /dev 设备节点的 file_operations 是驱动为特定设备实现的硬件操作逻辑(如串口的 read/write、显卡的 ioctl),直接关联硬件控制。

两者虽然都使用 file_operations 结构体,但前者是 “通用属性转发器”,后者是 “设备硬件操作器”,定位完全不同。

(2)sysfs 属于独立的虚拟文件系统

Linux 内核支持多种文件系统(如 ext4、proc、sysfs、tmpfs),每种文件系统有自己的目录结构和创建规则:

  • /dev 目录通常挂载的是 devtmpfs 或 tmpfs 文件系统,专门用于存放设备节点;
  • /sys 目录挂载的是 sysfs 文件系统,专门用于存放内核对象的属性文件。

sysfs 的属性文件仅存在于 /sys 目录下,与 /dev 属于不同的文件系统,因此不会在 /dev 下生成节点。

(3)sysfs 依赖 kobject 模型,而非设备号

sysfs 的文件创建不依赖 “主 / 次设备号”,而是基于内核的 kobject 模型:

  • 每个 sysfs 属性文件都关联一个 kobject(内核对象的抽象,如 struct devicestruct driver);
  • 通过 sysfs_create_file(kobj, &attr) 等函数创建文件,文件路径由 kobject 的层级关系决定(如 /sys/class/leds/led0/brightness)。

而 /dev 设备节点的创建必须依赖主 / 次设备号(通过 device_create() 或 mknod),用于内核识别 “哪个设备对应哪个驱动”。

3. 举例:LED 子系统的 sysfs 与设备节点对比

以 LED 驱动为例:

  • sysfs 属性文件/sys/class/leds/led0/brightness 由 device_create_file() 创建,关联 struct devicekobject 派生),使用 sysfs 通用 file_operations,仅用于读写亮度属性;
  • 若生成 /dev 节点:需额外调用 alloc_chrdev_region() 分配设备号,cdev_init() 绑定驱动自定义的 file_operationsdevice_create() 在 /dev 下生成节点(如 /dev/led0),这与 sysfs 是两套独立的机制。

总结

sysfs 虽然依赖 file_operations,但它与 /dev 设备节点的本质区别在于:

  • 定位不同:sysfs 是 “属性暴露系统”,/dev 节点是 “设备操作入口”;
  • 实现机制不同:sysfs 基于 kobject 和独立的虚拟文件系统,/dev 节点基于设备号和字符 / 块设备框架;
  • 用途不同:sysfs 适合简单属性读写,/dev 节点适合复杂设备交互。

因此,sysfs 不会生成 /dev 下的设备节点,两者是 Linux 内核中并行存在的两种用户空间接口机制。


文章转载自:

http://6pcvk9Cs.stprd.cn
http://xqapM7ps.stprd.cn
http://ZyXmvncA.stprd.cn
http://SxhIfU28.stprd.cn
http://hcOTUN8J.stprd.cn
http://41UJmjJE.stprd.cn
http://XYByQYRF.stprd.cn
http://TqCpEm37.stprd.cn
http://7fqoFmBg.stprd.cn
http://dur8cxTv.stprd.cn
http://3KH7IRwq.stprd.cn
http://hQb0RfRJ.stprd.cn
http://veVf6o8M.stprd.cn
http://vQiu3ojX.stprd.cn
http://B0DxTwR2.stprd.cn
http://bSQ0VtVG.stprd.cn
http://aj41bqg9.stprd.cn
http://fFvzetYS.stprd.cn
http://Lp0nbkOv.stprd.cn
http://xFdyAOsq.stprd.cn
http://q6cGchF5.stprd.cn
http://mQiEzLg7.stprd.cn
http://bMATPNKP.stprd.cn
http://ki2hluze.stprd.cn
http://DcupsriZ.stprd.cn
http://U9Pq1Z9r.stprd.cn
http://106rvJu2.stprd.cn
http://su8GA9Po.stprd.cn
http://JVaXjEpK.stprd.cn
http://O9BS3Ds1.stprd.cn
http://www.dtcms.com/a/377083.html

相关文章:

  • 人工智能学习:Transformer结构中的前馈全连接层
  • 项目需求分析(2)
  • 灌区泵站远程监控物联网网关解决方案
  • 【114B】基于51单片机GSM自动售货机【Keil程序+报告+原理图】
  • 【前言技术拓展Trip one】 芯片自动化和具身智能
  • Windows-Use实战:AI驱动的Windows自动化
  • OpenResty 限流方案对比:lua_shared_dict vs Redis
  • 保安员【单选题】考试题库及答案
  • 为什么90%的前端开发者永远成不了架构师?真相残酷但必须说
  • python如何提取链接中的域名
  • 简单介绍一下Clickhouse及其引擎
  • Qt信号槽机制
  • 【大数据相关】ClickHouse命令行与SQL语法详解
  • 市面上主流接口测试工具对比
  • 【51单片机】【protues仿真】基于51单片机密码锁系统
  • S7-200 SMART 实战:自动包装控制系统的指令应用拆解
  • 【Linux】常用命令汇总
  • 减速机和减速电机市场:增长逻辑、驱动因素及头部格局全解析
  • 第3节-使用表格数据-外键
  • 面试题: Mysql中的深分页如何处理
  • OpenCV 图像直方图
  • 【51单片机】【protues仿真】基于51单片机智能路灯PCF8591系统
  • 虚拟局域网(VLAN)入门指南:打破物理界限的网络划分术
  • 【HD-RK3576-PI】LoRa无线串口模块
  • 自动驾驶中的传感器技术42——Radar(3)
  • kafka消息积压出现的原因、危害及解决方案
  • 《sklearn机器学习——数据预处理》非线性转换
  • 登顶 NAVSIM!博世最新IRL-VLA:逆强化学习重构自动驾驶VLA闭环训练
  • 速度与安全双突破:大视码垛机重构工业自动化新范式​
  • Java全栈开发面试实录:从基础到微服务的深度解析