基于diagnose-tools 学习字符设备

本文从处理diagnose - tools问题出发,介绍Linux字符设备使用及原理。先分析设备模型,包括sysfs文件系统、关键数据结构(kobject、cdev等)和设备模型组件;接着阐述字符设备驱动开发,涵盖重要数据结构、接口、组成,还对部分代码流程分析,并给出创建字符设备的例子。

前言

这段时间在处理一个diagnose-tools 工具的一个问题,发现diagnose-tools 会在某些情况导致下导致内核模块加载失败, 在测试中发现原来 /sys/class 这个目录都没有,导致后面的模块加载失败了。https://github.com/alibaba/diagnose-tools/issues/65

通过这个issue吧,算是初步理解了字符设备的使用和背后的原理吧,字符设备看起来使用简单,创建一个cdev,一个class, 一个device 然后关联起来就可以了,实际上背后的逻辑还是有点复杂了,牵涉到了 Linux 设备驱动管理这一大块知识点,下面我把针对字符设备的相关内容整理梳理下。

 

1、设备模型分析

sysfs 文件系统

sysfs 文件系统是一个类似于proc的基于内存的文件系统,用于将内核中的设备组织成层次化的结构,并把内核设备的详细数据以用户态的文件形式层次化的展示出来。其顶层目录主要有:

block 目录:  包含所有的块设备

device 目录: 包含系统所有设备,并根据设备挂接的总线类型来层次化展示。

bus 目录: 包含系统中所有的总线类型

drivers 目录: 包含系统中所有已注册的设备驱动

class 目录: 系统中的设备类型(如磁盘,网卡,声卡)

sysfs文件系统是一个虚拟的并且存在内存中的,所以重启后,就会丢失,它提供了一些方法,可以把内核中的数据结构、属性和用户空间相互链接。mount -t sysfs sysfs /sys 来把 sysfs 文件系统挂载到根目录下的 sys 目录,当然也可以手动挂载到其它目录。

总线、设备、驱动、类之间关系如图下所示:

图1:总线、设备、驱动、类之间关系

 

       关键数据结构

       kobject, kset

       kobject

       在sysfs里显示的每一个目录都对应一个 kobject ,sysfs目录下的树状结构是通过kobject建立连接的, kobject通过大量的链接构成一个多层次的体系结构,kobject的层次结构可以说是代表了linux设备模型,是linux设备模型的基本结构。

struct kobject {
	const char		*name;           //设备名称
	struct list_head	entry;       //用于kobject之间组成双向链表,与该kobject所属的kset里的list形成双向链表
	struct kobject		*parent;     //指向父对象
	struct kset		*kset;           //指向所属kset的指针
	struct kobj_type	*ktype;      //kobject类型结构体,包含kobject属性和销毁方法等
    struct kernfs_node	*sd;         //在sysfs中的路径
	struct kref		kref;            //引用计数,当为0的时候,就会被删除
	unsigned int state_initialized:1; //初始化状态,同时对kobject操作进步异常验证
	unsigned int state_in_sysfs:1;    //在sysfs中kobject的状态
	unsigned int state_add_uevent_sent:1;    //记录用户态上报的状态,仅记录是否上报,上报后是否被接收不是该字段关心的
	unsigned int state_remove_uevent_sent:1;  //同上
	unsigned int uevent_suppress:1;           //如果该字段为1,表示忽略所有上报的uevent事件
};

       其中的kref域表示该对象引用的计数,内核通过kref实现对象引用计数管理,内核提供两个函数kobject-get()、kobject-put(),分别用于增加和减少引用计数,当引用计数为0时,所有该对象使用的资源将被释放。

       在创建kobject的时候,会通过 kobject_add_internal 方法建立 kobject 与 kset 之间的连接,在这里还是对 parent 的设置,如果没有传入parent,那么该kobject的parent就设置为 kset 的 kobj,在这里 kset 的作用出现了。

static int kobject_add_internal(struct kobject *kobj)
{
	struct kobject *parent;

	parent = kobject_get(kobj->parent);

	/* join kset if set, use it as parent if we do not already have one */
	if (kobj->kset) {
		if (!parent)
			parent = kobject_get(&kobj->kset->kobj);
		kobj_kset_join(kobj);
		kobj->parent = parent;
	}
    在这里还是对 parent 的设置,如果没有传入parent,那么该kobject的parent就
设置为 kset 的 kobj,在这里 kset 的作用出现了。
    ........
}

       cdev

 对于kobject结构体,单独使用意义不大,linux通过将object嵌入到某个结构体中,这样这些结构体就能用到kobject结构体,比如字符设备 <linux/cdev.h> 中的 struct cdev 结构体,一个 cdev 结构体代表着一个字符设备。

struct cdev {
	struct kobject kobj;    //嵌入kobject 结构体
	struct module *owner;   //所属模块
	const struct file_operations *ops;  //file operation
	struct list_head list;
	dev_t dev;
	unsigned int count;
};

把 kobject嵌入到某个结构体中后,它就拥有了kobject的标准功能。更重要的是,拥有了kobj成员可以便其成为设备模型架构对象中的一部分。通过 cdev->kobj.parent 指向所属 kset->kobj,并且把 cdev->kobj.entry和 cdev->kobj.kset.list 建立链接,使其建立层次结构。

       kset

kobject 通常通过 kset 组织成层次化的结构,kset 是具有相同类型的 kobject 的集合。

struct kset {
	struct list_head list;   //这是一个链表头,和属于kset的kobject组成双向链表
	spinlock_t list_lock;    //自旋锁,用于访问时链表时同步
	struct kobject kobj;     //内嵌的kobject对象,所有属于这个kset的kobject的parent都指向这个内嵌的kobj, 此外,kset还依赖kobj维护引用计数,kset的引用计数实际上就是内嵌kobj的引用计数
	const struct kset_uevent_ops *uevent_ops; //kobject创建或被删除时会产生事件,kobject所属的kset过滤事件或给用户空间传递信息
};

 

图2 kobject和kset 对应关系

 

    设备模型组件

          devices 组件

              系统中任一设备类型都由一个struct device 结构体来描述。同时又向sysfs注册一个kset,即devices (/sys/devices),这个就表示系统中所有设备所在的kset。

struct device {
	struct device		*parent;     //指向父设备,在字符设备里这个值为空,不用关注

	struct kobject kobj;            //内嵌一个kobject对象
	const char		*init_name;     /* initial name of the device */
	const struct device_type *type;
	struct bus_type	*bus;		/* type of bus device is on */
	struct device_driver *driver;	/* which driver has allocated this
					   device */

	u32			id;	/* device instance */
	struct class		*class;    //指向设备所属的类
    void (*release) (struct device *dev);   //释放设备时所调用的方法
    .......
};

           classes 组件

系统中的设备类由 struct class 描述,表示某一类设备,对应于sysfs文件系统中的 /sys/class 目录。

class 是一个设备的高层视图,它抽象出了底层的实现细节,从而允许用户空间使用设备所提供的功能,而不用关心设备是如何工作的。在class中,设备是按功能来归类,比如网卡,网卡,磁盘。很多设备并不属于某个总线,比如我们的字符设备就不属于某个总线,所以我们这里也不介绍总线相关的知识,不属于总线的设备,在管理方面不同于属于总线的设备。虽然不属于总线,但是字符设备归属于某个确定的class。

struct class {
	const char		*name;          //类名
	struct module		*owner;     //模块名
	struct kobject			*dev_kobj;   //内嵌kobject,表示该类设备的引用计数管理

	void (*class_release)(struct class *class);   //释放class调用函数,在创建class时指定
	void (*dev_release)(struct device *dev);

	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	struct subsys_private *p;
};

 

其中 struct subsys_private *p 是代表类的集合

struct subsys_private {
	struct kset subsys;
	struct list_head interfaces;   //interfaces是一个链表头,用来链接class上的各个接口,字符设备这里相当于是空的。

	struct class *class;
    .......
};

类的创建会在 sysfs 文件系统的 class 目录下创建一个该类名的目录。

下面说明了设备模型对设备的管理

图3 设备模型

 

2、字符设备驱动开发

      字符设备驱动重要的数据结构

         字符设备的特点是以字节为单位,顺序传输,键盘,鼠标以及打印机都是属于字符设备,都可以用文件的形式表达出来,所以它的关键数据结构也和文件差不多,它们分别是file_operations, file, inode,以文件的方式提供给用户空间使用。这里不细列这些普通的文件类数据结构了。

      字符设备的接口

      字符设备使用struct cdev 结构体描述字符设备, struct cdev 定义在文件 linux/cdev.h 中

struct cdev {
	struct kobject kobj;   //内嵌的kobject对象,用于对该设备的线用计数
	struct module *owner;  //所属模块指针
	const struct file_operations *ops;  //文件操作结构体指针,该设备操作对应的VFS的接口函数
	struct list_head list;  
	dev_t dev;   //设备号,一个32位数据,高12位为主设备号,低20位为次设备号
	unsigned int count;
};

      cdev里的kobj->parent,在cdev里没有赋值,是个空0x0,和struct class里的kobj->parent 指向 kset->kobj 不一样。当cdev里的kobj->parent时为空时,parent_kobj = virtual_device_parent(dev); 会指定一个parent设备为 virtual。

      字符设备驱动的组成

         字符设备驱动可以简单概括为两部分

         1、字符设备的加载和卸载

         2、字符设备对应的文件系统操作函数

 

部分代码流程分析

register_chrdev

     register_chrdev

         __register_chrdev_region   找到合适的chrdevs,获取字符设备的设备编号,并初始化 char_device_struct.

        cdev = cdev_alloc();    初始化 cdev 结构体

        err = cdev_add     给cdev结构体赋相应值,这里并没有创建文件或者文件夹

 

class_create

     class_create    创建并初始化class 结构体

        __class_register

           kset_register

               kobject_add_internal(&k->kobj);
               kobject_uevent(&k->kobj, KOBJ_ADD);

 

device_create

     device_create   

        device_create_groups_vargs  创建 struct dev 结构体

            device_register -> device_add

                  kobj = get_device_parent(dev, parent);    创建 /sys/devices 下的 device parent目录,并指定 parent,字符设备的parent 是 virtual 

                 device_create_file    创建 device 

                device_add_class_symlinks     建立 device 和 class 的软链

               

创建字符设备例子

 以下基于diagnose-tools 的代码写了个创建字符设备的例子,方便快速掌握字符设备的使用。

/*
 * 简单的字符设备例子
 *
 * Copyright (C) 2020 wllabs.
 *
 * 作者: wllabs <wllabs@163.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

#include "uapi/diagnose.h"

#define DIAG_DEV_NAME "wl-diagnose-tools"
#define DIAG_IOCTL_TYPE_TEST 1

static int diag_dev_major = -1;
static struct class *diag_dev_class = NULL;
static struct device *diag_dev = NULL;

struct diag_dev {
    struct cdev cdev;
};

static long diag_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int ret = -EINVAL;
    int type, nr;

    type = _IOC_TYPE(cmd);
    nr = _IOC_NR(cmd);

    switch (type) {
    case DIAG_IOCTL_TYPE_TEST:
        if (nr == 1) {
            struct diag_ioctl_test val;

            ret = copy_from_user(&val, (void *)arg, sizeof(struct diag_ioctl_test));
            if (!ret) {
                val.out = val.in + 1;
                ret = copy_to_user((void *)arg, &val, sizeof(struct diag_ioctl_test));
            }
        }
        break;
    default:
        break;
    }

    return ret;
}

static int diag_open(struct inode *inode, struct file *file)
{
    __module_get(THIS_MODULE);

    return 0;
}

static int diag_release(struct inode *inode, struct file *file)
{
    module_put(THIS_MODULE);

    return 0;
}

static const struct file_operations diag_fops = {
    .open       = diag_open,
    .release    = diag_release,
    .unlocked_ioctl = diag_ioctl,
};

static char *diag_devnode(struct device *dev, umode_t *mode)
{
    if (mode)
	    *mode = S_IRUGO | S_IRWXUGO | S_IALLUGO;

    return kstrdup("wl-diagnose-tools", GFP_KERNEL);;
}

int diag_dev_init(void)
{
    int ret = 0;
    diag_dev_major = register_chrdev(0, DIAG_DEV_NAME, &diag_fops);;

    if (diag_dev_major < 0) {
        printk("wl-diagnose-tools: failed to register device\n");
        return diag_dev_major;
    }

    diag_dev_class = class_create(THIS_MODULE, DIAG_DEV_NAME);
    if (IS_ERR(diag_dev_class)) {
        ret = PTR_ERR(diag_dev_class);
        printk(KERN_ERR "wl-diagnose-tools: class_create err=%d", ret);
        unregister_chrdev(diag_dev_major, DIAG_DEV_NAME);

        return ret;
    }
    diag_dev_class->devnode = diag_devnode;

    diag_dev = device_create(diag_dev_class, NULL, MKDEV(diag_dev_major, 0), NULL, DIAG_DEV_NAME);
    if (IS_ERR(diag_dev)) {
        ret = PTR_ERR(diag_dev);
        printk(KERN_ERR "wl-diagnose-tools: device_create err=%d", ret);
        unregister_chrdev(diag_dev_major, DIAG_DEV_NAME);
        class_destroy(diag_dev_class);

        return ret;
    }

    return 0;
}

void diag_dev_cleanup(void)
{
    if (diag_dev_major >= 0) {
        unregister_chrdev(diag_dev_major, DIAG_DEV_NAME);
    }

    if (diag_dev != NULL) {
        device_destroy(diag_dev_class, MKDEV(diag_dev_major, 0));
    }

    if (diag_dev_class != NULL) {
        class_destroy(diag_dev_class);
    }

    diag_dev_major = -1;
    diag_dev = NULL;
    diag_dev_class = NULL;
}


static int __init diagnosis_init(void)
{
	int ret = 0;

	ret = diag_dev_init();
	if (ret)
		goto out_dev;

	printk("wl-diagnose-tools in diagnosis_init\n");

	return 0;

out_dev:
	return ret;
}

static void __exit diagnosis_exit(void)
{
	printk("wl-diagnose-tools in diagnosis_exit\n");
	diag_dev_cleanup();
}

module_init(diagnosis_init);
module_exit(diagnosis_exit);

MODULE_DESCRIPTION("Alibaba performance monitor module");
MODULE_AUTHOR("wllabs <wllabs@163.com>");
MODULE_LICENSE("GPL v2");

完整代码百度网盘链接: https://pan.baidu.com/s/1_ZPxSuVb9_pOckTMJvq0mw  密码: 3s5i

 

# 设置 Rtools 路径(注意路径中的空格) > rtools_path <- "F:/Bioinformatics software/R/rtools44" > > # 添加到系统 PATH > Sys.setenv(PATH = paste( + paste0(rtools_path, "/usr/bin"), + paste0(rtools_path, "/x86_64-w64-mingw32.static.posix/bin"), + Sys.getenv("PATH"), + sep = ";" + )) > > # 设置编译工具路径 > Sys.setenv(BINPREF = paste0(rtools_path, "/mingw64/bin/")) > > # 设置 MAKE 路径 > Sys.setenv(MAKE = paste0(rtools_path, "/usr/bin/make.exe")) > # 安装必要的诊断包 > install.packages(c("pkgbuild", "devtools")) 试开URL’https://cran.rstudio.com/bin/windows/contrib/4.5/pkgbuild_1.4.8.zip' 试开URL’https://cran.rstudio.com/bin/windows/contrib/4.5/devtools_2.4.6.zip' 程序包‘pkgbuild’打开成功,MD5和检查也通过 程序包‘devtools’打开成功,MD5和检查也通过 下载的二进制程序包在 C:\Users\10062\AppData\Local\Temp\Rtmp29q8PB\downloaded_packages里 > > # 验证 Rtools 是否被识别 > pkgbuild::find_rtools() [1] TRUE > > # 详细诊断 > pkgbuild::check_build_tools(debug = TRUE) Trying to compile a simple C file Running "F:/Bioinformatics software/R/R-4.5.1/bin/x64/Rcmd.exe" SHLIB foo.c F:/Bioinformatics software/R/rtools44/mingw64/bin/gcc -I"F:/Bioinformatics software/R/R-4.5.1/include" -DNDEBUG -I"F:/Bioinformatics software/R/rtools45/x86_64-w64-mingw32.static.posix/include" -O2 -Wall -std=gnu2x -mfpmath=sse -msse2 -mstackrealign -c foo.c -o foo.o /bin/sh: line 1: F:/Bioinformatics: No such file or directory make: *** [F:/Bioinformatics software/R/R-4.5.1/etc/x64/Makeconf:289: foo.o] Error 127 试开URL’https://cloud.r-project.org/bin/windows/Rtools/rtools44/files/rtools44-6459-6401.exe' Content type 'application/x-msdownload' length 451591776 bytes (430.7 MB) downloaded 430.7 MB 错误: Could not find tools necessary to compile a package Call `pkgbuild::check_build_tools(debug = TRUE)` to diagnose the problem.
10-19
PowerShell 7 环境已加载 (版本: 7.5.2) PS C:\Users\Administrator\Desktop> cd E:\AI_System PS E:\AI_System> python -m venv venv PS E:\AI_System> source venv/bin/activate # Linux/Mac source: The term 'source' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. PS E:\AI_System> venv\Scripts\activate # Windows (venv) PS E:\AI_System> pip install -r requirements.txt Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Requirement already satisfied: accelerate==0.27.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 1)) (0.27.2) Requirement already satisfied: aiofiles==23.2.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 2)) (23.2.1) Requirement already satisfied: aiohttp==3.9.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 3)) (3.9.3) Requirement already satisfied: aiosignal==1.4.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 4)) (1.4.0) Requirement already satisfied: altair==5.5.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 5)) (5.5.0) Requirement already satisfied: annotated-types==0.7.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 6)) (0.7.0) Requirement already satisfied: ansicon==1.89.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 7)) (1.89.0) Requirement already satisfied: anyio==4.10.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 8)) (4.10.0) Requirement already satisfied: async-timeout==4.0.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 9)) (4.0.3) Requirement already satisfied: attrs==25.3.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 10)) (25.3.0) Requirement already satisfied: bidict==0.23.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 11)) (0.23.1) Requirement already satisfied: blessed==1.21.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 12)) (1.21.0) Requirement already satisfied: blinker==1.9.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 13)) (1.9.0) Requirement already satisfied: certifi==2025.8.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 14)) (2025.8.3) Requirement already satisfied: cffi==1.17.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 15)) (1.17.1) Requirement already satisfied: charset-normalizer==3.4.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 16)) (3.4.3) Requirement already satisfied: click==8.2.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 17)) (8.2.1) Requirement already satisfied: colorama==0.4.6 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 18)) (0.4.6) Requirement already satisfied: coloredlogs==15.0.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 19)) (15.0.1) Requirement already satisfied: contourpy==1.3.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 20)) (1.3.2) Requirement already satisfied: cryptography==42.0.4 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 21)) (42.0.4) Requirement already satisfied: cycler==0.12.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 22)) (0.12.1) Requirement already satisfied: diffusers==0.26.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 23)) (0.26.3) Requirement already satisfied: distro==1.9.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 24)) (1.9.0) Requirement already satisfied: exceptiongroup==1.3.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 25)) (1.3.0) Requirement already satisfied: fastapi==0.116.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 26)) (0.116.1) Requirement already satisfied: ffmpy==0.6.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 27)) (0.6.1) Requirement already satisfied: filelock==3.19.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 28)) (3.19.1) Requirement already satisfied: Flask==3.0.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 29)) (3.0.2) Requirement already satisfied: Flask-SocketIO==5.3.6 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 30)) (5.3.6) Requirement already satisfied: flatbuffers==25.2.10 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 31)) (25.2.10) Requirement already satisfied: fonttools==4.59.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 32)) (4.59.1) Requirement already satisfied: frozenlist==1.7.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 33)) (1.7.0) Requirement already satisfied: fsspec==2025.7.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 34)) (2025.7.0) Requirement already satisfied: gpustat==1.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 35)) (1.1) Requirement already satisfied: gradio==4.19.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 36)) (4.19.2) Requirement already satisfied: gradio_client==0.10.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 37)) (0.10.1) Requirement already satisfied: h11==0.16.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 38)) (0.16.0) Requirement already satisfied: httpcore==1.0.9 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 39)) (1.0.9) Requirement already satisfied: httpx==0.28.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 40)) (0.28.1) Requirement already satisfied: huggingface-hub==0.21.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 41)) (0.21.3) Requirement already satisfied: humanfriendly==10.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 42)) (10.0) Requirement already satisfied: idna==3.10 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 43)) (3.10) Requirement already satisfied: importlib_metadata==8.7.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 44)) (8.7.0) Requirement already satisfied: importlib_resources==6.5.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 45)) (6.5.2) Requirement already satisfied: itsdangerous==2.2.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 46)) (2.2.0) Requirement already satisfied: Jinja2==3.1.6 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 47)) (3.1.6) Requirement already satisfied: jinxed==1.3.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 48)) (1.3.0) Requirement already satisfied: jsonschema==4.25.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 49)) (4.25.1) Requirement already satisfied: jsonschema-specifications==2025.4.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 50)) (2025.4.1) Requirement already satisfied: kiwisolver==1.4.9 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 51)) (1.4.9) Requirement already satisfied: loguru==0.7.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 52)) (0.7.2) Requirement already satisfied: markdown-it-py==4.0.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 53)) (4.0.0) Requirement already satisfied: MarkupSafe==2.1.5 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 54)) (2.1.5) Requirement already satisfied: matplotlib==3.10.5 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 55)) (3.10.5) Requirement already satisfied: mdurl==0.1.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 56)) (0.1.2) Requirement already satisfied: mpmath==1.3.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 57)) (1.3.0) Requirement already satisfied: multidict==6.6.4 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 58)) (6.6.4) Requirement already satisfied: narwhals==2.1.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 59)) (2.1.2) Requirement already satisfied: networkx==3.4.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 60)) (3.4.2) Requirement already satisfied: numpy==1.26.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 61)) (1.26.3) Requirement already satisfied: nvidia-ml-py==13.580.65 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 62)) (13.580.65) Requirement already satisfied: onnxruntime==1.17.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 63)) (1.17.1) Requirement already satisfied: openai==1.13.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 64)) (1.13.3) Requirement already satisfied: orjson==3.11.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 65)) (3.11.2) Requirement already satisfied: packaging==25.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 66)) (25.0) Requirement already satisfied: pandas==2.1.4 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 67)) (2.1.4) Requirement already satisfied: pillow==10.4.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 68)) (10.4.0) Requirement already satisfied: prettytable==3.16.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 69)) (3.16.0) Requirement already satisfied: propcache==0.3.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 70)) (0.3.2) Requirement already satisfied: protobuf==6.32.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 71)) (6.32.0) Requirement already satisfied: psutil==5.9.7 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 72)) (5.9.7) Requirement already satisfied: pycparser==2.22 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 73)) (2.22) Requirement already satisfied: pydantic==2.11.7 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 74)) (2.11.7) Requirement already satisfied: pydantic_core==2.33.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 75)) (2.33.2) Requirement already satisfied: pydub==0.25.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 76)) (0.25.1) Requirement already satisfied: Pygments==2.19.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 77)) (2.19.2) Requirement already satisfied: pyparsing==3.2.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 78)) (3.2.3) Requirement already satisfied: pyreadline3==3.5.4 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 79)) (3.5.4) Requirement already satisfied: python-dateutil==2.9.0.post0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 80)) (2.9.0.post0) Requirement already satisfied: python-dotenv==1.0.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 81)) (1.0.1) Requirement already satisfied: python-engineio==4.12.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 82)) (4.12.2) Requirement already satisfied: python-multipart==0.0.20 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 83)) (0.0.20) Requirement already satisfied: python-socketio==5.13.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 84)) (5.13.0) Requirement already satisfied: pytz==2025.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 85)) (2025.2) Requirement already satisfied: pywin32==306 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 86)) (306) Requirement already satisfied: PyYAML==6.0.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 87)) (6.0.2) Requirement already satisfied: redis==5.0.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 88)) (5.0.3) Requirement already satisfied: referencing==0.36.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 89)) (0.36.2) Requirement already satisfied: regex==2025.7.34 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 90)) (2025.7.34) Requirement already satisfied: requests==2.31.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 91)) (2.31.0) Requirement already satisfied: rich==14.1.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 92)) (14.1.0) Requirement already satisfied: rpds-py==0.27.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 93)) (0.27.0) Requirement already satisfied: ruff==0.12.10 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 94)) (0.12.10) Requirement already satisfied: safetensors==0.4.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 95)) (0.4.2) Requirement already satisfied: semantic-version==2.10.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 96)) (2.10.0) Requirement already satisfied: shellingham==1.5.4 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 97)) (1.5.4) Requirement already satisfied: simple-websocket==1.1.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 98)) (1.1.0) Requirement already satisfied: six==1.17.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 99)) (1.17.0) Requirement already satisfied: sniffio==1.3.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 100)) (1.3.1) Requirement already satisfied: starlette==0.47.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 101)) (0.47.2) Requirement already satisfied: sympy==1.14.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 102)) (1.14.0) Requirement already satisfied: tokenizers==0.15.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 103)) (0.15.2) Requirement already satisfied: tomlkit==0.12.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 104)) (0.12.0) Requirement already satisfied: torch==2.1.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 105)) (2.1.2) Requirement already satisfied: tqdm==4.67.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 106)) (4.67.1) Requirement already satisfied: transformers==4.37.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 107)) (4.37.0) Requirement already satisfied: typer==0.16.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 108)) (0.16.1) Requirement already satisfied: typing-inspection==0.4.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 109)) (0.4.1) Requirement already satisfied: typing_extensions==4.14.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 110)) (4.14.1) Requirement already satisfied: tzdata==2025.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 111)) (2025.2) Requirement already satisfied: urllib3==2.5.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 112)) (2.5.0) Requirement already satisfied: uvicorn==0.35.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 113)) (0.35.0) Requirement already satisfied: waitress==2.1.2 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 114)) (2.1.2) Requirement already satisfied: wcwidth==0.2.13 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 115)) (0.2.13) Requirement already satisfied: websockets==11.0.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 116)) (11.0.3) Requirement already satisfied: Werkzeug==3.1.3 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 117)) (3.1.3) Requirement already satisfied: win32_setctime==1.2.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 118)) (1.2.0) Requirement already satisfied: wsproto==1.2.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 119)) (1.2.0) Requirement already satisfied: yarl==1.20.1 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 120)) (1.20.1) Requirement already satisfied: zipp==3.23.0 in e:\ai_system\venv\lib\site-packages (from -r requirements.txt (line 121)) (3.23.0) WARNING: typer 0.16.1 does not provide the extra 'all' [notice] A new release of pip available: 22.3.1 -> 25.2 [notice] To update, run: python.exe -m pip install --upgrade pip (venv) PS E:\AI_System> python diagnose_modules.py ============================================================ 模块文件诊断报告 ============================================================ 🔍 检查 CognitiveSystem 模块: 预期路径: E:\AI_System\agent\cognitive_architecture.py ✅ 文件存在 ✅ 找到类定义: class CognitiveSystem ✅ 类继承CognitiveModule ✅ 找到__init__方法 📋 初始化方法: def __init__(self, name: str, model_manager, config: dict = None): 🔍 检查 EnvironmentInterface 模块: 预期路径: E:\AI_System\agent\environment_interface.py ✅ 文件存在 ✅ 找到类定义: class EnvironmentInterface ❌ 类未继承CognitiveModule ✅ 找到__init__方法 📋 初始化方法: def __init__( 🔍 检查 AffectiveSystem 模块: 预期路径: E:\AI_System\agent\affective_system.py ✅ 文件存在 ✅ 找到类定义: class AffectiveSystem ✅ 类继承CognitiveModule ✅ 找到__init__方法 📋 初始化方法: def __init__(self, coordinator=None, config=None): ============================================================ 建议解决方案: ============================================================ 1. 检查每个模块文件中的相对导入语句 2. 确保每个模块类都正确继承CognitiveModule 3. 检查初始化方法的参数是否正确 4. 确保模块内部的导入使用绝对路径或正确处理相对导入 5. 考虑使用try-catch包装模块内部的导入语句 (venv) PS E:\AI_System> python test_core_import.py E:\Python310\python.exe: can't open file 'E:\\AI_System\\test_core_import.py': [Errno 2] No such file or directory (venv) PS E:\AI_System> python diagnose_architecture.py ============================================================ AI系统架构诊断报告 ============================================================ 1. 模块文件检查: ---------------------------------------- ✅ CognitiveSystem: E:\AI_System\agent\cognitive_architecture.py ✅ EnvironmentInterface: E:\AI_System\agent\environment_interface.py ✅ AffectiveSystem: E:\AI_System\agent\affective_system.py 2. Agent目录结构 (E:\AI_System\agent): ---------------------------------------- 📄 action_executor.py 📁 affective_modules/ 📄 affective_system.py 📄 agent_core.log 📄 agent_core.py 📄 autonomous_agent.py 📄 auto_backup.bat 📄 base_module.py 📄 cognitive_architecture.py 📁 cognitive_system/ 📄 communication_system.py 📁 concrete_modules/ 📄 conscious_framework.py 📁 conscious_system/ 📁 decision_system/ 📄 enhanced_cognitive.py 📄 environment.py 📄 environment_interface.py 📄 env_loader.py 📁 generated_images/ 📄 health_system.py 📄 knowledge graph.db 📁 knowledge_system/ 📄 main.py 📄 maintain_workspace.py 📄 memory_manager.py 📁 memory_system/ 📄 meta_cognition.py 📄 minimal_model.py 📁 models/ 📄 model_learning.py 📄 model_manager.py 📄 notepad 📄 performance_monitor.py 📄 pip 📄 security_manager.py 📄 self_growth.bat 📄 shortcut_resolver.py 📄 system_maintain.bat 📁 tests/ 📄 test_my_models.py 📁 text_results/ 📄 unified_learning.py 📁 utils/ 📄 world_view.py 📄 __init__.py 📁 __pycache__/ 3. 建议下一步: ---------------------------------------- 📍 所有模块文件都存在,需要检查模块实现内容 诊断完成 (venv) PS E:\AI_System> (venv) PS E:\AI_System> python main.py 2025-08-30 12:33:34,919 - CoreConfig - INFO - 🌐 从 E:\AI_System\.env 加载环境变量 2025-08-30 12:33:34,923 - CoreConfig - INFO - 📄 加载配置文件: E:\AI_System\config\config.json 2025-08-30 12:33:34,924 - CoreConfig - INFO - ✅ 配置系统初始化完成 2025-08-30 12:33:34,932 - Main - INFO - 日志系统初始化完成 (级别: INFO) 2025-08-30 12:33:34,936 - Main - INFO - ================================================== 2025-08-30 12:33:34,936 - Main - INFO - 🚀 启动AI系统 - 核心认知模式 2025-08-30 12:33:34,937 - Main - INFO - ================================================== 2025-08-30 12:33:34,941 - Main - INFO - 系统配置摘要: 2025-08-30 12:33:34,941 - Main - INFO - 项目根目录: E:\AI_System 2025-08-30 12:33:34,941 - Main - INFO - 默认模型路径: E:/AI_Models/Qwen2-7B 2025-08-30 12:33:34,946 - Main - INFO - 日志级别: INFO 2025-08-30 12:33:34,956 - ModelManager - INFO - ✅ 模型管理器初始化完成 (GPU: 启用) 2025-08-30 12:33:34,962 - ModelManager - INFO - 模型注册表: ['TEXT_BASE', 'TEXT_CHAT'] 2025-08-30 12:33:34,964 - Main - INFO - ✅ 模型管理器初始化完成 2025-08-30 12:33:34,964 - ModelManager - INFO - 加载模型: TEXT_BASE (E:/AI_Models/Qwen2-7B) 2025-08-30 12:33:34,964 - Main - INFO - ✅ 基础模型已加载: E:/AI_Models/Qwen2-7B 2025-08-30 12:33:34,964 - 小蓝 - INFO - ✅ 初始化认知模块: 小蓝 2025-08-30 12:33:34,964 - 小蓝 - INFO - ✅ 初始化认知模块: 小蓝 2025-08-30 12:33:34,964 - CognitiveSystem.小蓝 - INFO - ✅ 认知系统初始化完成 (版本 1.2.0) 2025-08-30 12:33:34,964 - CognitiveSystem.小蓝 - INFO - 当前模式: TASK_EXECUTION 2025-08-30 12:33:34,964 - Main - INFO - ✅ 认知系统初始化完成 - 名称: 小蓝 2025-08-30 12:33:34,964 - 环境接口 - INFO - ✅ 初始化环境模块: 环境接口 2025-08-30 12:33:34,964 - 环境接口 - INFO - ✅ 初始化环境模块: 环境接口 2025-08-30 12:33:34,964 - 环境接口 - INFO - ✅ 环境接口初始化完成 - Coordinator: 已连接 2025-08-30 12:33:34,964 - 环境接口 - INFO - ✅ 环境接口初始化完成 - Coordinator: 已连接 2025-08-30 12:33:34,964 - 环境接口 - INFO - ✅ 环境接口初始化完成 - Coordinator: 已连接 2025-08-30 12:33:34,964 - Main - INFO - ✅ 环境接口初始化完成 2025-08-30 12:33:34,964 - CommandListener - INFO - 🔊 启动命令监听器 2025-08-30 12:33:34,965 - CommandListener - INFO - ✅ 命令监听器已就绪,输入 'help' 查看可用命令 > 2025-08-30 12:33:34,966 - Main - INFO - ✅ 命令监听器已启动 2025-08-30 12:33:34,966 - Main - INFO - 🌟 系统准备就绪! 输入命令控制模式 (输入 'help' 查看可用命令) > help > 2025-08-30 12:33:49,519 - CommandListener - INFO - 📩 收到命令: help === 高级命令系统 === 基础命令: help - 显示此帮助信息 exit/quit - 退出系统 status - 查看系统状态 mode [mode]- 切换工作模式 (reflect, task, learn) 多行输入: 输入多行命令时,在最后一行以 ;; 结束 例如: update user set name = John Doe;; > exit > 2025-08-30 12:34:03,357 - CommandListener - INFO - 📩 收到命令: exit 2025-08-30 12:34:03,357 - CommandListener - INFO - 🛑 收到退出命令 2025-08-30 12:34:03,357 - Main - INFO - 🛑 收到关闭命令,开始关闭系统... 2025-08-30 12:34:03,357 - CommandListener - INFO - 🛑 正在停止命令监听器... 2025-08-30 12:34:03,450 - Main - INFO - 🛑 收到关闭命令,开始关闭系统... 2025-08-30 12:34:03,451 - 环境接口 - INFO - 🛑 停止环境接口... 2025-08-30 12:34:03,451 - 环境接口 - INFO - 🛑 停止环境接口... 2025-08-30 12:34:03,451 - 环境接口 - INFO - 🛑 停止环境接口... 2025-08-30 12:34:03,451 - Main - INFO - ✅ 系统已完全关闭 (venv) PS E:\AI_System> model model: The term 'model' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. (venv) PS E:\AI_System> model model: The term 'model' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. (venv) PS E:\AI_System> diagnose module diagnose: The term 'diagnose' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. (venv) PS E:\AI_System> python main.py 2025-08-30 12:34:58,926 - CoreConfig - INFO - 🌐 从 E:\AI_System\.env 加载环境变量 2025-08-30 12:34:58,926 - CoreConfig - INFO - 📄 加载配置文件: E:\AI_System\config\config.json 2025-08-30 12:34:58,926 - CoreConfig - INFO - ✅ 配置系统初始化完成 2025-08-30 12:34:58,927 - Main - INFO - 日志系统初始化完成 (级别: INFO) 2025-08-30 12:34:58,927 - Main - INFO - ================================================== 2025-08-30 12:34:58,927 - Main - INFO - 🚀 启动AI系统 - 核心认知模式 2025-08-30 12:34:58,927 - Main - INFO - ================================================== 2025-08-30 12:34:58,927 - Main - INFO - 系统配置摘要: 2025-08-30 12:34:58,927 - Main - INFO - 项目根目录: E:\AI_System 2025-08-30 12:34:58,927 - Main - INFO - 默认模型路径: E:/AI_Models/Qwen2-7B 2025-08-30 12:34:58,927 - Main - INFO - 日志级别: INFO 2025-08-30 12:34:58,927 - ModelManager - INFO - ✅ 模型管理器初始化完成 (GPU: 启用) 2025-08-30 12:34:58,927 - ModelManager - INFO - 模型注册表: ['TEXT_BASE', 'TEXT_CHAT'] 2025-08-30 12:34:58,928 - Main - INFO - ✅ 模型管理器初始化完成 2025-08-30 12:34:58,928 - ModelManager - INFO - 加载模型: TEXT_BASE (E:/AI_Models/Qwen2-7B) 2025-08-30 12:34:58,928 - Main - INFO - ✅ 基础模型已加载: E:/AI_Models/Qwen2-7B 2025-08-30 12:34:58,928 - 小蓝 - INFO - ✅ 初始化认知模块: 小蓝 2025-08-30 12:34:58,928 - 小蓝 - INFO - ✅ 初始化认知模块: 小蓝 2025-08-30 12:34:58,928 - CognitiveSystem.小蓝 - INFO - ✅ 认知系统初始化完成 (版本 1.2.0) 2025-08-30 12:34:58,928 - CognitiveSystem.小蓝 - INFO - 当前模式: TASK_EXECUTION 2025-08-30 12:34:58,928 - Main - INFO - ✅ 认知系统初始化完成 - 名称: 小蓝 2025-08-30 12:34:58,928 - 环境接口 - INFO - ✅ 初始化环境模块: 环境接口 2025-08-30 12:34:58,928 - 环境接口 - INFO - ✅ 初始化环境模块: 环境接口 2025-08-30 12:34:58,928 - 环境接口 - INFO - ✅ 环境接口初始化完成 - Coordinator: 已连接 2025-08-30 12:34:58,928 - 环境接口 - INFO - ✅ 环境接口初始化完成 - Coordinator: 已连接 2025-08-30 12:34:58,928 - 环境接口 - INFO - ✅ 环境接口初始化完成 - Coordinator: 已连接 2025-08-30 12:34:58,928 - Main - INFO - ✅ 环境接口初始化完成 2025-08-30 12:34:58,929 - CommandListener - INFO - 🔊 启动命令监听器 2025-08-30 12:34:58,930 - CommandListener - INFO - ✅ 命令监听器已就绪,输入 'help' 查看可用命令 > 2025-08-30 12:34:58,930 - Main - INFO - ✅ 命令监听器已启动 2025-08-30 12:34:58,930 - Main - INFO - 🌟 系统准备就绪! 输入命令控制模式 (输入 'help' 查看可用命令) > model > 2025-08-30 12:35:10,507 - CommandListener - INFO - 📩 收到命令: model 2025-08-30 12:35:10,508 - Main - INFO - 🔄 处理命令: model 2025-08-30 12:35:10,508 - CognitiveSystem.小蓝 - INFO - 🧠 处理命令: model 💬 系统响应: • status: success • content: 正在处理您的请求: ... > diagnose modules > 2025-08-30 12:35:24,736 - CommandListener - INFO - 📩 收到命令: diagnose modules 2025-08-30 12:35:24,736 - Main - INFO - 🔄 处理命令: diagnose modules 2025-08-30 12:35:24,736 - CognitiveSystem.小蓝 - INFO - 🧠 处理命令: diagnose modules 💬 系统响应: • status: success • content: 正在处理您的请求: modules... >
08-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值