- 博客(300)
- 收藏
- 关注
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍1
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:59
599
2
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍4
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:44
1008
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍2
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:36
908
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍3
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:32
869
1
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍5
引言随着越来越多功能强大的高级语言的出现,在服务器计算能力不是瓶颈的条件下,很多同学会选择开发效率高,功能强大的虚拟机支持的高级语言(Java),或者脚本语言(Python,Php)作为实现功能的首选,而不会选择开发效率低,而运行效率高的 C/C++ 作为开发语言。而这些语言一般情况下是运行在虚拟机或者解释器中,而不需要直接跟操作系统直接打交道。虚拟机和解释器相当于为高级语言或者脚本语言提供了一个中间层,隔离了与操作系统之间进行交互的细节,这为工程师们减少了很多与系统底层打交道的麻烦,大大提高了工程
2025-01-10 22:14:24
896
1
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍6
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:21
667
4
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍7
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:17
594
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍8
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:14
995
2
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍9
引言随着越来越多功能强大的高级语言的出现,在服务器计算能力不是瓶颈的条件下,很多同学会选择开发效率高,功能强大的虚拟机支持的高级语言(Java),或者脚本语言(Python,Php)作为实现功能的首选,而不会选择开发效率低,而运行效率高的 C/C++ 作为开发语言。而这些语言一般情况下是运行在虚拟机或者解释器中,而不需要直接跟操作系统直接打交道。虚拟机和解释器相当于为高级语言或者脚本语言提供了一个中间层,隔离了与操作系统之间进行交互的细节,这为工程师们减少了很多与系统底层打交道的麻烦,大大提高了工程
2025-01-10 22:14:11
959
1
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍10
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:07
783
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍11
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:04
864
1
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍12
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:14:01
976
1
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍13
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:13:57
650
1
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍14
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:13:54
668
原创 高级语言(Java\Python\Php)的编译:链接及装载过程介绍15
这里我们看到了nm命令的输出默认有三列,其中最左边的一列是变量的相对地址,中间的一列表示变量所在的段的类型,右面表示变量的名字。我们在C源码文件部分曾经提到过,变量和函数的声明本质上是给编译器一个承诺,告诉编译器虽然在本文件中没有这个变量或者函数定义,但是在其他文件中一定有,所以当编译器发现程序需要读取这个变量对应的数据,但是在源文件中找不到的时候,就会把这个变量放在一个特殊的段(段类型为 U)里面,表示后续链接的时候需要在后面的目标文件或者链接库中找到这个变量,然后链接成为可执行二进制文件。
2025-01-10 22:13:51
981
1
原创 Kafka文件存储机制那些事15
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:42
898
原创 Kafka文件存储机制那些事14
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:39
637
1
原创 Kafka文件存储机制那些事13
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:36
942
原创 Kafka文件存储机制那些事12
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:32
764
原创 Kafka文件存储机制那些事11
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:30
739
1
原创 Kafka文件存储机制那些事10
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:27
750
原创 Kafka文件存储机制那些事9
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:24
522
1
原创 Kafka文件存储机制那些事8
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:22
732
3
原创 Kafka文件存储机制那些事7
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:20
685
2
原创 Kafka文件存储机制那些事6
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:17
830
原创 Kafka文件存储机制那些事5
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:15
832
1
原创 Kafka文件存储机制那些事4
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:13
705
原创 Kafka文件存储机制那些事3
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:10
617
2
原创 Kafka文件存储机制那些事2
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:07
670
1
原创 Kafka文件存储机制那些事1
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
2025-01-09 22:47:02
812
原创 Java内存访问重排序的研究1
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:04:19
579
原创 Java内存访问重排序的研究2
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:04:15
980
3
原创 Java内存访问重排序的研究3
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:04:12
842
2
原创 Java内存访问重排序的研究4
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:04:09
786
4
原创 Java内存访问重排序的研究5
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:04:05
718
原创 Java内存访问重排序的研究6
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:03:50
794
2
原创 Java内存访问重排序的研究7
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:03:46
758
原创 Java内存访问重排序的研究8
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:03:42
314
2
原创 Java内存访问重排序的研究9
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:03:32
757
原创 Java内存访问重排序的研究10
a = 1;x = b;});b = 1;y = a;});one.join();很容易想到这段代码的运行结果可能为(1,0)、(0,1)或(1,1),因为线程one可以在线程two开始之前就执行完了,也有可能反之,甚至有可能二者的指令是同时或交替执行的。然而,这段代码的执行结果也可能是(0,0). 因为,在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。得到(0,0)结果的语句执行过程,如下图所示。
2025-01-08 20:03:23
949
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人