软硬件开辟面试问题大汇总篇——针对非通例八股问题的提问与应答 ...

打印 上一主题 下一主题

主题 1747|帖子 1747|积分 5241

软硬件开辟,从微控制器编程到复杂的嵌入式系统开辟,离不开下位机、操作系统、上位机等,涵盖范围很广。

如何快速一行代码操作硬件寄存器

直接操作硬件寄存器的代码通常依赖于特定平台和编程语言。在 C 或 C++ 中,常见的方法是使用指针来访问内存地址。假设通过芯片手册知道要操作的寄存器的地址:
  1. #define REG_ADDRESS 0x12345678       // 假设这是硬件寄存器的地址
  2. *(volatile int *)REG_ADDRESS = 0x1;  // 将值 0x1 写入寄存器
复制代码
注意事项:
   

  • 权限:在某些系统上,你可能需要特权(如操作系统内核模式)才能直接访问硬件寄存器。
  • 平台依赖性:不同的硬件架构和开辟情况会有不同的方法来访问寄存器,因此确保参考相干文档。
  • 范例安全性:根据具体应用选择合适的数据范例,以制止潜在的问题。
  如何最快比较两组寄存器里有多少位不同

要比较两组寄存器的位差异,可以使用按位异或(XOR)操作。通过将两个寄存器的值举行异或运算,结果中的每一位都可以指示这两个值在相应位置上是否不同。然后,统计结果中“1”的数量即为不同位的数量。
  1. #include <iostream>
  2. // 计算二进制中 1 的个数
  3. int countSetBits(unsigned int n) {
  4.     int count = 0;
  5.     while (n) {
  6.         count += n & 1; // 每次检查最低位
  7.         n >>= 1;        // 右移一位
  8.     }
  9.     return count;
  10. }
  11. int main() {
  12.     unsigned int regA = 0b11001100; // 假设第一个寄存器的值
  13.     unsigned int regB = 0b10101010; // 假设第二个寄存器的值
  14.     unsigned int diff = regA ^ regB; // 按位异或运算
  15.     int numDifferences = countSetBits(diff); // 统计不同位数
  16.     std::cout << "Different bits: " << numDifferences << std::endl;
  17.     return 0;
  18. }
复制代码

如何降低功耗

硬件层

⑴选择低功耗芯片和组件
在设计系统时,优先选用具有低功耗特性的微控制器(MCU)、微处置惩罚器(MPU)或其他集成电路。例如,一些专为低功耗物联网应用设计的芯片,其在就寝模式下功耗可以到达微安甚至纳安级别。这些芯片通常接纳了先辈的制程技能,可以或许有用降低静态功耗。对于外围设备,如传感器和通信模块,也应选择低功耗型号。以传感器为例,某些加速率传感器在低功耗模式下可以以极低的频率举行数据收罗,从而大大淘汰功耗。
⑵电源管理芯片的合理应用
接纳高效的电源管理芯片(PMIC)来优化电源分配和转换服从。PMIC 可以根据系统的不同工作状态,动态调解输出电压和电流,以满意各个组件的现实需求。例如,在系统处于待机状态时,PMIC 可以降低对某些非关键组件的供电电压,从而淘汰待机功耗。利用 PMIC 的电源域划分功能,将不同功耗特性的组件划分到不同的电源域。这样可以在不需要某些组件工作时,直接关闭其所在的电源域,实现功耗的大幅降低。
⑶优化硬件电路设计
淘汰不必要的电路元件和毗连。例如,在电路板布线时,尽量缩短电源线和地线的长度,以降低线路电阻,淘汰功率损耗。合理设置上拉电阻和下拉电阻的值,制止过大的电流消耗。同时,对于一些不常用的输入引脚,可以通过配置为低功耗模式(如模仿输入模式)来淘汰漏电流。

软件层

⑴动态电源管理计谋
实施基于任务的电源管理。根据系统实行的任务,动态调解硬件组件的电源状态。例如,在一个具有蓝牙通信功能的设备中,当不需要举行蓝牙数据传输时,可以将蓝牙模块置于低功耗就寝模式。只有在需要发送或接收数据时,才唤醒蓝牙模块。接纳动态电压和频率缩放(DVFS)技能。对于支持 DVFS 的处置惩罚器,软件可以根据当前的负载情况,动态调解处置惩罚器的工作电压和频率。在系统负载较低时,降低电压和频率,以淘汰功耗;在负载较高时,提高电压和频率,确保系统性能。
⑵优化代码和算法
编写高效的代码,淘汰 CPU 的实行时间。例如,优化循环结构,制止不必要的盘算和重复操作。在一个数据处置惩罚应用中,假如可以通过预先盘算一些常量或者接纳更高效的算法来淘汰循环中的盘算量,就能缩短 CPU 的工作时间,从而降低功耗。对于通信协议栈,优化协议的实现方式,淘汰通信过程中的数据传输量和传输频率。例如,在物联网设备与服务器之间的通信中,可以接纳数据压缩技能,淘汰每次传输的数据量,进而降低通信模块的功耗。
⑶合理设置就寝模式和唤醒机制
充实利用芯片的低功耗就寝模式。不同的芯片通常提供多种就寝模式,如浅就寝、深就寝等。软件应根据系统的现实需求,选择合适的就寝模式。例如,在一个周期性收罗传感器数据的设备中,当设备等候下一次收罗时,可以将芯片置于深就寝模式,此时芯片的大部门电路都被关闭,只有一个低功耗的定时器在运行,用于唤醒芯片。优化唤醒机制,确保系统可以或许快速、正确地从就寝模式中唤醒,并且在唤醒后可以或许尽快进入正常工作状态。可以通过设置合适的中断触发条件来实现高效的唤醒。例如,使用外部中断引脚来检测传感器数据停当信号,当信号到来时,立刻唤醒芯片举行数据收罗。

系统层

⑴优化系统架构和工作流程
接纳分布式架构来降低系统整体功耗。例如,在一个大型的工业监控系统中,将数据收罗和初步处置惩罚任务分配到多个低功耗的边缘设备上,这些设备仅在必要时将处置惩罚后的数据发送给中心服务器,制止了大量数据的长间隔传输和集中处置惩罚带来的高功耗。优化系统的工作流程,淘汰不必要的任务和操作。例如,在一个智能家居系统中,通过合理设置主动化规则,制止设备的频繁开启和关闭,从而降低设备的总体功耗。
⑵能源网络和增补技能
思量接纳能量网络技能,如太阳能电池板、压电质料(用于网络机器能转化为电能)、热电质料(网络热能转化为电能)等。对于一些低功耗的物联网设备,这些能量网络技能可以在一定程度上增补设备的电能消耗,延伸电池寿命或者实现无电池运行。结合储能技能,如超等电容器或高性能电池,合理管理网络到的能量和设备的能量消耗,确保系统在不同的能源供应和需求情况下都能稳固运行。

如何高效处置惩罚中断

硬件层

⑴合理设置中断优先级
很多微控制器和处置惩罚器都支持中断优先级机制。通过对不同中断源设置合理的优先级,可以确保关键的中断可以或许及时得到处置惩罚。例如,在一个同时包罗定时器中断和外部通信中断的系统中,假如通信中断对于实时性的要求更高,如接收紧急的控制指令,那么应该将通信中断的优先级设置得高于定时器中断。这样,当通信中断发生时,可以或许优先处置惩罚通信数据,制止因定时器中断的干扰而导致通信数据丢失或延迟。相识硬件的中断嵌套功能。一些高级的硬件平台允许高优先级中断打断低优先级中断的处置惩罚过程。在设计系统时,需要谨慎使用中断嵌套,由于过分的嵌套可能会导致栈溢出或系统复杂性增加。但在某些对实时性要求极高的场景下,合理的中断嵌套可以有用地提高系统的相应速率。
⑵优化中断控制器设置
正确配置中断控制器的触发方式(如边沿触发或电平触发)。边沿触发适合于只需要检测信号变化瞬间的情况,例如按键按下的瞬间产生的中断;电平触发则实用于需要在信号保持特定电平期间一连相应的情况,如检测外部设备的停当信号。选择合适的触发方式可以制止不必要的中断产生。对于具有中断屏蔽功能的中断控制器,合理地屏蔽息争除屏蔽中断。在进入关键代码段(如对共享资源举行操作的代码)时,可以暂时屏蔽一些可能会干扰当前操作的中断,待操作完成后再解除屏蔽。但要注意,过长时间地屏蔽中断可能会导致系统对外部变乱的相应延迟,因此需要谨慎权衡。

软件层

⑴接纳中断上半部和下半部机制
中断上半部用于处置惩罚紧急的、对时间要求极高的操作。例如,在网络设备接收数据的中断中,上半部可以快速读取接收到的数据寄存器中的数据,将数据存储到一个临时缓冲区中,并设置一个标志位表示数据已接收。这个过程应该尽可能地快速,以淘汰中断相应时间。中断下半部用于处置惩罚那些相对不紧急、可以延迟处置惩罚的操作。好比,对接收的数据举行复杂的协议解析、数据处置惩罚等操作可以放在下半部。常见的实现下半部的方式有软中断、tasklet(在 Linux 内核中有广泛应用)等。这样可以制止在中断处置惩罚程序中实行过多耗时的操作,从而淘汰对系统实时性的影响。
⑵优化中断服务程序(ISR)代码
保持中断服务程序的代码简便高效。制止在 ISR 中举行复杂的盘算、大量的循环或函数调用。例如,尽量淘汰乘法、除法等耗时的算术运算。假如必须举行一些复杂的操作,可以思量将其分解为多个简单的步骤,将一部门步骤移到中断下半部或者其他合适的地方处置惩罚。淘汰中断服务程序中的内存分配和释放操作。内存分配操作通常涉及到复杂的内存管理算法,可能会导致中断处置惩罚时间变长。假如需要使用缓冲区来存储数据,可以在系统初始化时预先分配好,或者接纳静态分配的方式。
⑶使用合适的并发控制机制
当多个中断可能会访问共享资源(如全局变量、硬件寄存器等)时,需要使用合适的并发控制机制。例如,在多中断情况下,可以使用自旋锁或互斥锁来保护共享资源。自旋锁实用于锁被占用时间较短的情况,由于它会让等候锁的线程(在中断处置惩罚程序中可以看作是等候锁的中断处置惩罚过程)一直循环等候,直到锁被释放;互斥锁则实用于锁可能被长时间占用的情况,当锁不可用时,等候的线程会进入就寝状态,制止浪费 CPU 资源。对于中断与主程序(进程或线程)之间共享资源的情况,也需要举行有用的同步。可以通过信号量、条件变量等机制来实现。例如,当主程序需要访问一个可能会被中断修改的变量时,先获取相应的信号量,确保在访问期间不会被中断修改,访问完成后再释放信号量。

系统层

⑴负载平衡思量
在多核处置惩罚器系统中,思量将中断处置惩罚任务平衡地分配到不同的核心上。有些硬件平台支持中断亲和性设置,即可以指定某个中断由特定的核心来处置惩罚。通过合理地分配中断,可以制止某个核心负载过重,而其他核心闲置的情况,从而提高系统的整体性能。对于一些高负载的中断源,可以接纳分布式处置惩罚的方式。例如,在一个大型的数据收罗系统中,假如有多个类似范例的传感器产生中断,可以将这些中断分配到不同的处置惩罚单元(可以是不同的处置惩罚器核心或者不同的微控制器)举行预处置惩罚,然后再将处置惩罚后的结果汇总,这样可以有用地减轻单个处置惩罚单元的负担。
⑵性能测试与调优
利用性能测试工具来监测中断处置惩罚的性能。例如,在嵌入式系统中,可以使用示波器来测量中断相应时间,通过在中断引脚触发中断的同时,在另一个引脚输出一个时间标志信号,然后观察这两个信号之间的时间差来确定中断相应时间。在操作系统情况下,可以使用系统自带的性能监测工具或者第三方工具来监测中断处置惩罚过程中的 CPU 使用率、中断延迟等指标。根据性能测试的结果,针对性地举行调优。假如发现某个中断的相应时间过长,可以检查该中断的服务程序代码、优先级设置、硬件毗连等方面是否存在问题,并举行相应的优化。同时,还可以通过调解系统参数(如中断队列长度、定时器周期等)来改善中断处置惩罚的性能。


delay和sleep的区别

⑴功能目的
delay:主要用于在程序实行过程中产生一个短时间的延迟,通常用于精确控制时间隔断,好比在微控制器编程中控制硬件设备的时序,像在驱动 LED 闪耀时,控制亮灭之间的时间隔断。sleep:目的是让实行线程或进程停息实行一段时间,更侧重于让程序在一段时间内进入休眠状态,以释放 CPU 资源或等候某些条件满意,例如在一个多任务系统中,让一个进程停息运行,使其他任务可以占用 CPU。
⑵应用场景
delay:常见于嵌入式系统和硬件相干的编程,特别是对时间精度要求较高的操作,如控制电机的转速、产生特定频率的脉冲信号等。也用于一些简单的顺序程序中,在两个操作之间插入短暂延迟,实现简单的时间控制。sleep:多用于操作系统情况下的多任务编程。例如,在服务器程序中,让一个不需要一直占用 CPU 的任务进入就寝状态,等候客户端请求到来;或者在下令行工具中,让程序停息实行,模仿长时间运行任务中的等候阶段。
⑶实现方式和对系统的影响
delay:实现方式可能因平台而异,在一些简单的微控制器中,通过循环等候系统时钟计数到达一定值来实现,这种方式会占用 CPU 资源,在延迟期间 CPU 无法实行其他任务。但在某些具有硬件定时器支持的系统中,它可以利用定时器来实现,此时 CPU 可以在延迟期间实行其他任务。sleep:在操作系统中,会使调用它的线程或进程进入壅闭状态,操作系统会调理其他停当的任务运行。当就寝时间竣事,线程或进程会重新进入停当状态,等候系统调理实行。它是一种基于操作系统调理机制的停息方式,对系统的资源管理和任务调理有着良好的支持。

中断时可否就寝

在处置惩罚器中,中断和就寝是两个不同的概念,通常它们之间是相互独立的。
1.中断处置惩罚
中断(Interrupt) 是由硬件或软件变乱触发的信号,用于停息当前实行的程序,以便处置惩罚某些紧急任务(如输入输出操作、定时器到期等)。中断服务例程(ISR)是在发生中断后实行的特别代码,必须敏捷完成以规复主程序的实行。
2.就寝状态
就寝通常意味着让当前线程或进程停息一段时间,不再占用 CPU 资源。在某些编程情况和操作系统中,可以调用 sleep 或 delay 函数来实现这一点。
3.在中断上下文中的就寝
通常情况下,在处置惩罚中断服务例程(ISR)时是不应当调用任何可能导致线程就寝的函数。这是由于:假如 ISR 被中断并进入休眠状态,会造成系统不相应其他紧张的变乱,从而引发延迟或丢失数据。大多数操作系统会禁止在 ISR 中使用壅闭操作,以确保实时性和相应速率。
4.合适的位置
一般来说,假如需要在某个条件下举行就寝,你应该在非中断上下文中实行。你可以设置一个标志位或信号量,由主循环监测该标志位,当条件满意时再举行适当的休眠。
使用 ISR 和主循环来控制行为:
  1. volatile bool condition = false;
  2. void interrupt_handler() {
  3.     // 中断服务例程
  4.     // 设置某个条件
  5.     condition = true;
  6. }
  7. int main() {
  8.     while (true) {
  9.         if (condition) {
  10.             // 执行一些操作
  11.             
  12.             // 重置条件
  13.             condition = false;
  14.         } else {
  15.             // 可以安全地调用 sleep,而不是在 ISR 中调用
  16.             sleep(1); // 或 delay(1000);
  17.         }
  18.     }
  19. }
复制代码

如何设计RAM和flash的验证工具

设计一个用于验证RAM和Flash存储器的工具涉及多个步骤,包罗需求分析、硬件选择、软件开辟和测试等。以下是一个高条理的设计流程:
需求分析



  • 目标:明确要验证的功能,例如读写速率、数据完整性、错误检测与改正(ECC)、耐久性等。
  • 情况:确定将在那里运行该工具(嵌入式系统、PC等)。
  • 接口:确认需要使用哪些通信接口(如SPI, I2C, UART)。
硬件选择



  • 选择适当的硬件平台举行验证,例如单片机或FPGA。
  • 确定需要毗连的RAM和Flash范例及其规格。
软件架构设计

⑴模块划分
初始化模块:负责配置RAM和Flash存储器,设置必要的控制寄存器。
读写模块


  • 提供读写操作API。
  • 实现数据模式(例如,随机/顺序读取与写入)。
校验模块


  • 使用 CRC 或哈希算法对数据举行完整性检查。
  • 实现错误检测与更正机制(如 ECC)。
⑵测试用例设计
根据需求定义具体的测试用例,例如:


  • 写入特定模式并读取,比较结果是否一致。
  • 随机访问测试,确保随机读写性能符合预期。
  • 在不同温度、电压条件下举行耐久性测试。
开辟与实现

使用适合的平台编程语言举行编码,例如 C/C++ 或 Python 等,并基于需要处置惩罚实时任务时选用相应语言。
代码框架(伪代码)
  1. void initialize_memory() {
  2.     // 初始化 RAM 和 Flash 配置
  3. }
  4. bool write_to_flash(uint32_t address, uint8_t *data, size_t length) {
  5.     // 写入数据到 Flash 存储器
  6. }
  7. bool read_from_flash(uint32_t address, uint8_t *buffer, size_t length) {
  8.     // 从 Flash 中读取数据
  9. }
  10. void verify_data(uint8_t *original_data, uint8_t *read_data, size_t length) {
  11.     // 比较原始数据和读取的数据,返回验证结果
  12. }
复制代码
测试实行

实行编写好的测试用例并网络结果。可思量使用日记记载功能以便后续分析问题。
分析与陈诉

根据测试结果生成详细陈诉,包罗通过率、不通过原因,以及可能的改进发起。
常见挑战及解决方案


  • 兼容性问题:不同范例内存具有不同的协议,需要提供抽象层来统一管理这些不同内存设备。
  • 性能瓶颈:确保在测试过程中不会引入额外延迟影响正常性能评估。
  • 硬件故障检测:增加自检功能,可以帮助快速识别硬件故障导致的问题。

如何合理高效静态分配内存

静态分配内存是指在程序编译时就确定了内存的大小和位置,这种方法通常用于确定不会在运行时改变大小的数据结构。合理高效的静态分配内存可以帮助提高程序性能并淘汰运行时错误。
数据结构设计



  • 选择合适的数据结构:根据应用需求选择最适合的数据结构(例如,数组、结构体等)。
  • 制止过分设计:尽量简化数据结构,确保其只包罗必要的信息。
内存划分



  • 合理划分模块:将不同功能的变量和数据放置在不同的区域,以提高可读性和维护性。
  • 常量与全局变量:使用常量来替代不需要更改的值,并将全局变量限定到最低限度,以淘汰潜在冲突。
范例与大小



  • 精确范例选择:根据现实需求选择数据范例。例如,假如只需要表示0到255之间的整数,可以使用uint8_t而不是int。
  • 预留冗余空间:在某些情况下,适当预留额外的空间可以制止频繁地重新定义内存大小,如为数组添加一个元素以便后续扩展或处置惩罚边界情况。
编译器优化



  • 利用编译器特性:很多当代编译器提供了优化选项,可以通过指定不同的优化级别来改善生成代码的性能。
  • 内联函数:对于频繁调用的小函数,可以思量使用内联函数来淘汰函数调用带来的开销。
确保可移植性

平台独立性:尽量制止依赖特定平台的实现细节,好比直接操作硬件地址,而应通过标准API举行交互。
例程
  1. #include <stdint.h>
  2. #define MAX_ITEMS 100
  3. typedef struct {
  4.     uint8_t id;
  5.     char name[50];
  6. } Item;
  7. static Item inventory[MAX_ITEMS]; // 静态分配内存
  8. // 函数声明
  9. void addItem(uint8_t id, const char* name);
  10. void printInventory(void);
  11. // 添加物品到库存
  12. void addItem(uint8_t id, const char* name) {
  13.     static int count = 0; // 计数器,静态保存状态
  14.     if (count < MAX_ITEMS) {
  15.         inventory[count].id = id;
  16.         strncpy(inventory[count].name, name, sizeof(inventory[count].name) - 1);
  17.         count++;
  18.     }
  19. }
  20. // 打印库存内容
  21. void printInventory(void) {
  22.     for (int i = 0; i < MAX_ITEMS; i++) {
  23.         if (inventory[i].id != 0) { // 假设0表示未用物品
  24.             printf("ID: %d, Name: %s\n", inventory[i].id, inventory[i].name);
  25.         }
  26.     }
  27. }
复制代码
开辟经验:
   

  • 调试信息记载:静态分配可能导致难以排查的问题,特别是在复杂系统中。适当记载调试信息,有助于后期维护。
  • 资源管理:虽然静态分配不会出现动态分配中的泄漏问题,但也要注意防止超出所定义边界访问内存。
  • 跨平台兼容性:假如筹划让程序支持多种硬件或操作系统,要过细审视各种边界条件下如何管理这些静态资源。
  
如何跟踪内存泄漏

内存泄漏是指程序在运行过程中分配了内存但未能及时释放,导致这些内存块无法被使用,最终可能导致系统资源耗尽。
使用工具

有多种专门的工具可以帮助检测和分析内存泄漏:


  • Valgrind:这是一个强盛的开源工具,用于检查C/C++程序中的内存管理问题,包罗内存泄漏。
  1. valgrind --leak-check=full ./your_program
复制代码


  • AddressSanitizer (ASan):这是GCC和Clang提供的一种编译器工具,可以用来检测C/C++代码中的内存错误,包罗缓冲区溢出、使用后释放等。在编译时加上-fsanitize=address选项:
  1. gcc -fsanitize=address -g your_code.c -o your_program
复制代码


  • Visual Studio 的诊断工具:假如在Windows上使用Visual Studio,可以利用其自带的分析工具来检测内存泄漏。
手动跟踪

假如不想依赖第三方工具,可以通过设计内存分配接口,手动的方法举行简单的内存跟踪
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define MAX_ALLOCATIONS 100
  4. typedef struct {
  5.     void* ptr;
  6.     size_t size;
  7. } Allocation;
  8. static Allocation allocations[MAX_ALLOCATIONS];
  9. static int allocation_count = 0;
  10. void* tracked_malloc(size_t size) {
  11.     if (allocation_count >= MAX_ALLOCATIONS) {
  12.         printf("Memory limit reached!\n");
  13.         return NULL;
  14.     }
  15.    
  16.     void* ptr = malloc(size);
  17.     if (ptr != NULL) {
  18.         allocations[allocation_count++] = (Allocation){ptr, size};
  19.     }
  20.     return ptr;
  21. }
  22. void tracked_free(void* ptr) {
  23.     for (int i = 0; i < allocation_count; i++) {
  24.         if (allocations[i].ptr == ptr) {
  25.             free(ptr);
  26.             // Remove from the tracking array
  27.             allocations[i] = allocations[--allocation_count]; // 简单的移除方法,但不是最优雅的处理方式。
  28.             return;
  29.         }
  30.     }
  31. }
  32. void report_memory_leaks() {
  33.     if (allocation_count > 0) {
  34.         printf("Memory leaks detected:\n");
  35.         for (int i = 0; i < allocation_count; i++) {
  36.             printf("Leaked memory at %p of size %zu\n", allocations[i].ptr, allocations[i].size);
  37.         }
  38.     } else {
  39.         printf("No memory leaks detected.\n");
  40.     }
  41. }
  42. int main() {
  43.    // 使用tracked_malloc和tracked_free替代malloc和free
  44.    
  45.    int* arr = (int*)tracked_malloc(10 * sizeof(int));
  46.    
  47.    // ... 忘记释放 arr ...
  48.    
  49.    report_memory_leaks(); // 程序结束前调用报告函数
  50.    return 0;
  51. }
复制代码
编写测试用例

单元测试
编写测试用例,在每次分配内存后举行释放,并确认所有分配都得到了相应的释放。这种方式可以帮助早期发现潜在的问题。
开辟经验:​​​​​​​
   

  • 定期举行代码检察,以确保团队成员理解并遵循正确的内存管理实践。
  • 对于复杂的数据结构,如链表、树或图,尤其要注意每个节点的动态分配和释放过程。
  • 为制止遗漏,使用智能指针(如 C++ 中的 std::unique_ptr 和 std::shared_ptr)主动管理资源。
  



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表