自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

一起学嵌入式

分享Linux、RTOS、C/C++等嵌入式技术内容

  • 博客(62)
  • 收藏
  • 关注

原创 嵌入式 C 语言合集,基础到进阶

嵌入式软件开发,C语言是必须要掌握好的。嵌入式C语言变量、数组、指针初始化的多种操作。全面讲解 C 语言的结构体(struct)【进阶】嵌入式 C 语言代码优化的一些措施。嵌入式 C 语言实现面向对象编程的三大特性。如何搞定嵌入式 C 语言中的全局变量问题。内存拷贝函数 memcpy 的原理及实现。嵌入式设备驱动程序构建"库"的一些思想。嵌入式 C 语言宏定义的常用方法总结。GCC对C语言扩展语法归纳详解(一)GCC对C语言扩展语法归纳详解(二)GCC对C语言扩展语法归纳详解(三)

2024-02-05 23:14:51 411

原创 这些嵌入式知识助你秋招,也助你进阶

更多内容请去公众号【一起学嵌入式】查阅。未完待续…

2023-09-14 13:04:17 272 1

原创 关于串口通信丢帧问题的处理

这种一问一答的方式,虽然可以保证数据传输的可靠性。难免会存在传输效率低的问题。如果发送的数据包比较多,可否等到数据包全部发送完成后,最后再统一进行校验处理呢?这种处理该如何做呢?大家有兴趣可以思考一下。

2023-08-10 14:43:53 416

原创 FreeRTOS编码标准与数据类型

宏均是由大写字母表示,并配有小写字母的前缀, 前缀用于表示该宏在哪个头文件定义。比如宏定义。

2023-07-21 14:19:43 298

原创 RTOS任务切换过程中堆栈的使用情况

SVC(系统服务调用,亦简称系统调用)和 PendSV(可悬起系统调用),它们多用于在操作系统之上的软件开发中。SVC 用于产生系统函数的调用请求。SVC 异常通过执行 ”SVC” 指令来产生。该指令需要一个立即数, 充当系统调用代号。SVC异常服务例程稍后会提取出此代号, 从而解释本次调用的具体要求, 再调用相应的服务函数。例如,SVC 0x3;调用 3 号系统服务在 SVC 服务例程执行后,上次执行的 SVC 指令地址可以根据自动入栈的返回地址计算出。

2023-07-09 16:22:11 225

原创 51单片机也可以移植RTOS

点击Keil工程配置按钮【Options for Target】-> 【Target】-> 【C251】 -> 【Define】 输入。点击【Target】-> 【Exeternal Memory】-> 【ROM】 起始地址:0xFE2000 大小:0x1E000。点击【Target】-> 【C251】 -> 【Define】 输入 configSUPPORT_MCS251。点击【Target】-> 【C251】 -> 【Define】 输入 configSUPPORT_MCS251。

2023-05-11 14:08:14 1630 1

原创 eeprom读写数据不一致问题分析

从地址 0x02 连续写入 8 个字节,其中,前六个字节可以正确写入,写入到地址 0x02~0x07 中。按照页写规则,后两个字节的地址,在 0x07 基础上递增,会回转到页面首地址 0x00~0x01,即最后两个字节会写入到地址 0x00~0x01 中。如上图,AT24C02 可以按照字节写,也可以按照页写。连续读取多个字节的时候,没有 “页” 的限制,地址按照顺序递增,若达到存储器的地址末尾,则自动回转到0地址。地址: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07。

2023-04-26 11:11:01 2225

原创 FreeRTOS 官方中文版网站上线啦

FreeRTOS官网中文版上线

2023-01-10 15:58:12 3372 2

原创 FreeRTOS快速入门-初探FreeRTOS

首发,公众号【一起学嵌入式】对于 RTOS 入门系列文章,已经更新完一款(RT-Thread):助你快速入门 RT-Thread这个系列的文章结合 RT-Thread,介绍过 RTOS 相关的核心知识。接下来,开始另外一款 RTOS – FreeRTOS 入门系列,希望能够帮助初学者快速掌握 FreeRTOS,帮助老手回顾基础内容。一起学习、一起进步。加油~FreeRTOS简介先来看看官网介绍,官方网址https://freertos.org/FreeRTOS 是一种面向微控制器.

2022-04-22 11:23:16 10299 4

原创 RT-Thread快速入门-文章汇总

为了方便阅读,将《RT-Thread快速入门》系列文章进行了汇总。主要包括以下部分:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qrR6okrH-1650596699763)(%E6%B1%87%E6%80%BB%E5%9B%BE%E7%A4%BA.png)]文章列表如下,点击即可直接阅读:RT-Thread 学习-Env开发环境搭建RT-Thread快速入门-初探RT-ThreadRT-Thread快速入门-体验RT-ThreadRT-Thread快速入门-了

2022-04-22 11:07:54 605

原创 RT-Thread快速入门-内核移植

首发,公众号【一起学嵌入式】RT-Thread 快速入门系列前面的文章介绍了内核相关的知识,以及内核提供的接口函数和如何使用。本篇文章主要介绍如何将 RT-Thread 内核移植到某个硬件平台之上。移植分为两部分:CPU 架构移植BSP 移植也就是将 RT-Thread 内核在不同的芯片架构、不同的板卡上运行起来,能够具备线程管理和调度,内存管理,线程间同步和通信,定时器管理等功能。CPU 架构移植,会用到 CPU 架构的汇编指令,因此如果要自己动手移植,需要熟悉一下目标 CPU 的汇编.

2022-04-21 11:09:09 588

原创 RT-Thread快速入门-中断管理

首发,公众号【一起学嵌入式】经过前面文章的学习,对于 RT-Thread 处理多任务或者说线程的处理机制,基本上入门了。能够上手用 RT-thread 进行日常开发了。但是,还有一个重要的部分,那就是 RT-Thread 如何处理中断。说到中断,大家都不会陌生,对于裸机编程,很简单,编写指定的中断服务函数就可以了。如果工程建立在 RTOS 基础之上,中断是如何管理的呢?本文带你了解 RT-Thread 的中断处理过程,以及如何添加中断服务程序和相关的注意事项。RT-Thread 中断工作机制.

2022-04-13 15:19:32 3702

原创 RT-Thread快速入门-内存池

首发,公众号【一起学嵌入式】引言上篇文章介绍了动态内存堆相关的内容:RT-Thread快速入门-动态内存堆管理这篇文章继续介绍 RT-Thread 内存管理剩下的部分——内存池。为何引入内存池?内存堆虽然方便灵活,但是存在明显的缺点:分配效率低。每次分配内存的时候,都需要查找空闲内存块。容易产生内存碎片。为了规避这两个问题,RT-Thread 提供了内存池(Memory Pool)的管理机制。理解内存池内存池用于分配大小相同的小内存块,可以极大地提高内存分配和释放的速度,且避免.

2022-04-07 09:57:06 509

原创 如何配置 VirtualBox 虚拟机的网络模式

首发,公众号【一起学嵌入式】最近有小伙伴遇到虚拟机网络通信的问题。本文以 VirtualBox 为例梳理一下虚拟机的网络设置。为什么是 VitualBox,因为这款虚拟机软件免费,简单易用,性能也很优异。完全能够满足日常使用。闲话少絮,步入正题。网络接入模式VirtualBox 提供了 7 种网络接入模式,如下图所示:这 7 种模式分别是:网络地址转换(Network Address Translation,NAT)模式桥接网卡模式内部网络模式仅主机网络模式通用驱动NAT .

2022-03-28 15:32:10 3053

原创 RT-Thread快速入门-动态内存堆管理

首发,公众号【一起学嵌入式】每种 RTOS 均有内存管理机制,RT-Thread 的内存管理分为两类:动态内存堆管理、内存池管理。本篇文章先来介绍一下动态内存堆管理相关的内容。内存堆管理机制RT-Thread 操作系统在内存管理上,根据上层应用及系统资源的不同,有针对性地提供了不同的内存分配管理算法。内存堆管理根据具体内存设备划分为三种情况:针对小内存块的分配管理(小内存管理算法);针对大内存块的分配管理(slab 管理算法);针对多内存堆的分配情况(memheap 管理算法).

2022-03-26 13:58:54 789

原创 RT-Thread快速入门-信号

首发,公众号【一起学嵌入式】对,你没看错。作为一款 RTOS,RT-Thread 提供了 Linux 才有的信号机制。其他常用的 RTOS 没有提供信号机制。在 Linux 中,信号作为进程间通信的一种方式。而在 RT-Thread 中,仿照类似的原理,实现信号机制,用于线程(任务)间通信。本篇文章,我们来学习 RT-Thread 信号的相关内容,以及如何进行管理和使用。信号的工作机制同 Linux 中的信号类似,是一种软件层次的中断。在 RT-Thread 中,信号用作异步通信。POSIX.

2022-03-24 11:29:28 8041 3

原创 RT-Thread快速入门-消息队列

首发,公众号【一起学嵌入式】哈哈,RT-Thread 快速入门系列文章登上官方论坛 “今日聚焦” 了,能够得到官方认可,属实受宠若惊。感谢 RT-Thread 的认可,感谢官方提供的交流学习平台。继续努力,持续输出 RT-Thread 相关的技术文章。加油~RT-Thread 官方论坛地址为:https://club.rt-thread.org/index.html正文开始上一篇介绍了消息邮箱,本篇文章介绍线程(任务)间通信的另一种方式——消息队列。消息队列在实际项目中应用较多,建议初.

2022-03-18 12:50:36 6603 4

原创 RT-Thread快速入门-消息邮箱

首发,公众号【一起学嵌入式】前面几篇文章介绍了线程(任务)间的同步机制:信号量、互斥量、事件集。接下来我们学习线程(任务)之间的通信机制。一般来说,RTOS 均会提供两种线程间通信的机制:消息邮箱和消息队列。RT-Thread 同样如此。本篇文章介绍 RT-Thread 消息邮箱相关的内容。邮箱的工作机制1. 理解消息邮箱邮箱是一种简单的线程间消息传递的方式,其特点是开销较低,效率较高。邮箱中的每一封邮件可以容纳固定大小的内容(针对 32 位处理器,可容纳 4 字节内容,所以一封邮件恰好可以.

2022-03-15 09:38:36 1352

原创 RT-Thread快速入门-事件集

首发,公众号【一起学嵌入式】RT-Thread 中的事件集,也就是其他 RTOS 中的事件标志组。事件集也是线程(任务)间同步的一种机制。前面介绍的两种线程间同步的方式(信号量和互斥量)都是一对一;而事件集可以实现一对多、多对多的线程同步。事件集的工作机制1. 理解事件集多个事件的集合用一个 32 位无符号整型变量来表示,变量的每一位代表一个事件,线程通过 “逻辑与” 或 “逻辑或” 将一个或多个事件关联起来,形成事件组合。RT-Thread 中的事件集有以下特点:事件只与线程相关,事件.

2022-03-03 18:12:43 1884

原创 RT-Thread快速入门-互斥量

首发,公众号【一起学嵌入式】引言互斥量,即互斥信号量(Mutex,Mutual Exclusion 的缩写)。互斥量的主要作用是对资源实现互斥访问。二值信号量也可以实现对资源的互斥访问,那么为何要引入互斥量呢?互斥量和信号量有什么不同呢?这其中涉及到两个重要的知识点:优先级翻转优先级继承理解了这两点内容,互斥量也就基本掌握了。理解互斥量互斥量是一种保护共享资源的方法,当一个线程拥有互斥量时,可以保护共享资源不被其他线程破坏。一个线程持有互斥量时,其他线程不能再持有它,持有该互斥量的.

2022-02-22 14:02:16 1570 3

原创 RT-Thread快速入门-线程间同步之信号量

首发,公众号【一起学嵌入式】,RTOS、Linux、C线程同步是指多个线程通过某种特定的机制,来控制线程之间的先后执行顺序。RT-Thread 提供了几种线程同步的方式:信号量(semaphore)、 互斥量(mutex)、和事件集(event)。本篇文章主要介绍信号量相关的内容。信号量的工作机制信号量是一种可以用来解决线程间同步问题的内核对象,线程通过获取和释放信号量,来达到同步的目的。每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值表示信号对象的实例数目或者资源数目;线程等待队.

2022-02-16 13:00:14 1675

原创 Linux编程入门(19)-信号(上)

公众号【一起学嵌入式】,专注RTOS、Linux、C引言在 Linux 终端运行一个程序后,如果要终止其运行,会通过键盘输入 Ctrl-C。这背后蕴含着怎样的处理机制呢?其实,当输入 Ctrl-C 后,会产生一个中断信号(SIGINT)。shell 接收到这个信号后,就会结束当前正在执行的工作,并将控制返回到 shell 主循环中,再次向用户呈现 shell 的提示符。本文来学习一下 Linux 中的信号:基本概念以及它的使用。信号是什么信号是 Linux 中一个简单而重要的概念。信号是事件.

2022-02-12 12:28:25 923

原创 RT-Thread快速入门-时钟管理

首发,公众号【一起学嵌入式】,精彩内容首先送达时钟节拍任何操作系统都需要提供一个时钟节拍,以供系统处理所有和时间有关的事件,如延时、线程的时间片轮转调度以及定时器超时等。时钟节拍(OS Tick)是操作系统中最小的时间单位。时钟节拍是特定的周期性中断,这个中断之间的时间间隔取决于具体的应用,一般是 1-100ms。时钟节拍率越快,系统的额外开销就越大。RT-Thread 中,一个时钟节拍的时长根据 rtconfig.h 配置文件中, RT_TICK_PER_SECOND 的 定 义 来 调 整,.

2022-02-08 23:11:11 1368

原创 RT-Thread快速入门-线程管理(下)

首发,公众号【一起学嵌入式】上一篇主要介绍了 RT-Thread 线程管理相关的理论知识:RT-Thread快速入门-线程管理这篇重点介绍 RT-thread 提供的线程管理相关的接口函数,以及实战演示。线程创建在 RT-Thread 中,创建一个线程的方式有两种:动态创建方式,线程的栈和线程控制块由系统从动态内存堆上分配。静态创建方式,线程的栈和线程控制块由用户定义分配。1. 动态创建线程动态创建线程,用户不需要考虑线程栈和线程控制块空间分配的问题,全部由系统自动完成分配。用户只.

2022-01-27 14:36:02 5223 1

原创 RT-Thread快速入门-线程管理(上)

首发,公众号【一起学嵌入式】在 RT-Thread 中,最基本的调度单位是线程,其他 RTOS 也叫任务。如果学习过或者了解过 RTOS,任务这种叫法是最为熟知的。本篇文章来学习一下 RT-Thread 线程方面的内容。对于初学者来说,转换一下思维,建立多任务(线程)的编程思想。引言对于裸机编程,整个软件系统只有一个线程(任务)在执行,实现方式是通过一个大循环完成的。应用程序是一个无限循环,循环中调用各个功能模块的函数,完成相应的操作。RTOS 是一个多任务系统,可以把总体功能划分为多个小模块.

2022-01-25 00:02:14 4006

原创 RT-Thread快速入门-了解内核启动流程

首发,公众号【一起学嵌入式】,RTOS、Linux、C内核是操作系统最基础也是最重要的部分。从本文开始进入 RT-Thread 内核相关知识的学习。首先了解内核的基础知识,对 RT-Thread 内核的设计有个初步的认识。然后了解一下 RT-Thread 系统启动流程。内核介绍下图为 RT-Thread 的内核架构图:内核包括两部分:内核库、实时内核实现。内核库为了保证内核能够独立运行,RT-Thread 设计了一套小型的类似 C 库的函数实现子集,根据编译器的不同 C 库的情况会有些.

2022-01-22 22:50:33 2207 1

原创 esp32学习-手把手搭建idf开发环境

首发,公众号【一起学嵌入式】前言偶然看到了吃灰多年的 esp32 开发板。先把板子上的灰吹吹,然后找了一根 USB 线,接上电脑。灯亮了,嗯,还能用。这块板子是 2018 年买的,三年多没玩这块板子了,乐鑫官网的开发软件包不知道更新多少个版本了。上官网查资料,尝试在 Windows 下搭建最新的 ESP-IDF 开发环境,准备玩玩这款高性能的开发板。当然,第一个测试程序,怎么能少得了 Hello world。OK,开始吧。环境搭建准备1. 安装必备的工具首先,需要在 PC 上安装 p.

2022-01-20 17:05:39 11336 4

原创 Linux 一道关于 fork 的笔试题

题目阅读下面的代码,显示终端会打印出几个 hello world?#include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(){ fork(); fork(); fork(); printf("hello world\n"); exit(0);}答案是多少呢?我们一起分析一下。原理分析关于 forkfork

2022-01-18 09:35:54 791

原创 C语言结构体大小 你算对了吗

C 语言中 struct 声明创建一个数据类型(结构体),能将不同类型的对象聚合到一个对象中,用名字来引用结构体的各个组成部分。结构体的所有组成部分都存放在一段连续的内存中。如果创建一个结构体,其实际占用的内存空间大小是多少呢?示例代码如下:struct S{ int i; char c; int j;};要正确计算结构体大小,首先需要了解数据对齐的原理。数据对齐许多计算机系统对基本的数据类型的合法地址做了一些限制。要求某种类型对象的地址必须是某个值(通常为2、4、8)的倍数。这种对齐

2022-01-14 09:36:12 282

原创 RT-Thread快速入门-体验RT-Thread

RT-Thread快速入门-体验RT-Thread在开始 RT-Thread 内核学习之前,先来体验一下 RT-Thread。要体验 RT-Thread,首先需要具备运行环境或者实验环境。RT-Thread 不仅可以在实际硬件平台上运行,也可以在虚拟环境下实验运行。如果只是为了学习内核知识,并配合练习实验,虚拟环境就可以了。如果有实际的硬件环境,当然会更好。官方的学习资料中,介绍了两种虚拟环境:QEMU 虚拟机Keil 模拟器下面分别以这两种环境体验一下 RT-Thread 运行。接着介

2022-01-13 10:16:58 1001

原创 RT-Thread快速入门-初探RT-Thread

一文带你了解 RT-Thread

2022-01-10 13:49:31 1585

原创 Linux设备驱动-字符设备驱动浅析

Linux 设备驱动分为三种:字符设备驱动、块设备驱动、网络设备驱动。内核针对每一类设备都提供了对应的驱动模型框架,包括基本的内核设施和文件系统接口。其中,字符设备驱动程序是最常见的,也是相对比较容易理解的一种。其典型的程序框架示例,如下:#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/cdev.h>/* 定义一个字符设备

2022-01-06 10:17:59 1044

原创 Linux编程入门(18)-进程(六)实现 shell

什么是 shellLinux 系统中,shell 是一个特殊的应用程序,它可以管理进程和运行程序。Linux 中有很多种 shell,每种都有自己的风格和优势。常用的 shell 都有三个主要的功能:运行程序例如,ls、cd、date 等都是一些普通程序,用 C 语言编写,并被编译成机器语言。shell 将它们载入内存并运行。也可以认为 shell 是一个程序启动器。管理输入和输出shell 不仅可以运行程序,还可以使用符号 <、> 和 | 将输入、输出重定向。告诉 shell

2022-01-02 00:27:18 1239

原创 Linux编程入门(17)-进程(五)运行全新的程序

前两篇文章介绍了进程的创建、退出,以及父进程等待子进程退出等相关内容:进程的创建和退出: Linux编程入门(15)-进程(三)编程 父进程等待子进程: Linux编程入门(16)-进程(四)等待子进程 在进行综合例程之前,还需弄明白一个问题:新创建的进程如何一个全新的程序?前面介绍过,父进程通过调用系统函数 fork() 创建一个子进程,子进程与父进程共用指令码,且子进程从 fork() 返回之后的指令码开始执行。有时候,在创建一个新进程之后,需要执行另一个程序,即运行一个全新的程序

2021-12-31 14:12:59 632

原创 Linux编程入门(16)-进程(四)等待子进程

上一篇介绍了进程的创建和退出,以及相关的系统函数。Linux编程入门(15)-进程(三)编程 这篇主要讲讲,子进程退出后,父进程如何获取其退出状态。有的应用程序,需要父进程知道子进程何时终止或退出,以及其返回给父进程的状态值信息。那么,父进程在创建完成子进程后,有没有办法获知子进程的退出状态?答案是肯定的。Linux 提供了系统函数 wait(),用于检测子进程的终止情况。系统函数 wait()系统函数 wait() 主要做两件事:暂停调用它的进程,直到有子进程退出。获取子进程结束时传递

2021-12-30 09:30:06 1213 3

原创 Linux编程入门(15)-进程(三)创建和终止

前面两篇文章学习了进程相关的理论基础,本文开始学习进程编程。Linux编程入门(13)-进程(一)Linux编程入门(14)-进程(二)创建进程系统函数 fork()Linux 提供了系统调用 fork() 用于创建一个新进程,其函数原型为:#include <sys/types.h>#include <unistd.h>pid_t fork(void);如果调用成功,函数 fork() 在父进程中返回子进程的 ID;在子进程中返回 0。若调用失败,则在父进程

2021-12-29 09:19:42 229 2

原创 Linux编程入门(14)-进程(二)

上一篇文章简单介绍了文件系统的基础知识,这篇继续学习文件系统的内容。Linux编程入门(8)-文件系统初步创建文件的过程文件有内容和属性,内核将文件内容存放在数据区,文件属性存放在 i 节点,文件名存放在目录中。创建一个新文件的主要操作步骤如下:1、存储属性先找到一个空的 i 节点,然后内核把文件的信息记录在这个 i 节点中。2、存储数据根据文件内容的大小,申请能够存储这个文件的磁盘块(假如需要 n 个磁盘块)。内核从空闲磁盘块列表中找出 n 个自由块。将文件内容存放在这些自由磁盘块中。3

2021-12-28 12:54:29 612

原创 C程序中与内存有关的常见错误

与内存有关的错误属于那种最令人惊恐的错误。在时间和空间上,经常在距离错误源一段距离之后才表现出来。将错误的数据写到错误的位置,你的程序可能在最终失败之前运行了一段时间。下面列举并分析与内存有关的几种错误:1、间接引用坏指针如果间接引用一个指向没有任何意义的数据的指针,那么操作系统会以段异常终止程序。如果向只读区域中写入数据,这些区域会以保护异常终止这个程序。一个常见的经典示例是 scanf 错误。这个函数用处是从标准输入读入一个整数到一个变量,正确的写法是传递给 scanf 一个格式串和变量的地址:

2021-12-27 17:45:49 736

原创 Linux编程入门(13)-进程(一)

学习 Linux 编程,非常重要的一个知识点,便是进程。那进程是什么?如何用进程编写程序呢?让我们逐步揭开进程的面纱,攻克它,使得进程为我所用。基础内容什么是进程运行一个程序意味着将机器指令序列载入内存,然后让 CPU 逐条执行这些指令。进程便是程序运行时的内存空间和设置。还有一种经典定义,进程是一个执行中程序的实例。Linux 在执行一个程序时,内核会将程序指令代码载入虚拟内存,为程序变量分配内存空间,建立记录进程信息的数据结构(如,进程 ID、用户 ID、组 ID、终止状态等)。从内核角度来看

2021-12-27 00:28:41 659

原创 Linux编程入门(12)-理解系统调用过程

Linux 提供了具有良好定义、数量有限、直接进入内核的入口点,这些入口点被称为系统调用。前面的文章学习了 Linux 文件以及文件系统操作的基础知识,并介绍了一些系统调用函数。那么应用程序在调用系统函数时,内核的处理流程是怎样的呢?在 Linux 系统中,分为用户空间和内核空间。从系统安全和稳定方面考虑,用户空间的程序不能直接执行内核代码或者操作内核数据。但是,内核以 API 的形式,提供了一系列服务供应用程序访问,是为了从内核获得某项服务或资源。系统调用过程从编程角度来说,系统调用与 C 语言函

2021-12-27 00:26:54 830

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除