2. 江苏航天龙梦信息技术有限公司, 苏州 215500;
3. 常熟理工学院 计算机科学与工程学院, 苏州 215500
2. Jiangsu Lemote Technology Co. Ltd., Suzhou 215500, China;
3. School of Computer Science and Engineering, Changshu Institute of Technology, Suzhou 215500, China
处理器设计的中心目标一直是最大限度地利用可用资源以实现最大性能. 在多核处理器中, 操作情况是不可预测的: 在有多个就绪的软件线程情况下, 可以通过并行执行更多线程来提高系统性能; 在其他情况下, 提高单线程性能是改善整个系统性能的唯一途径[1]. 为了更好地发挥单线程应用的性能, 处理器制造商相继提出睿频技术, 其中Intel的睿频技术为turbo boost technology[2]、AMD的睿频技术为turbo core technology[3]. 睿频技术在动态电压频率调节(dynamic voltage and frequency scaling, DVFS)基础上, 增加了允许CPU频率超过默频的特性. 与以前通过降低CPU时钟频率和电压来节省能源的DVFS[4-6]工作相反, 当多核处理器具有空闲资源时, 睿频技术降低空闲核心的功耗, 提高活跃核心的CPU时钟频率, 侧重于在热设计功耗(thermal design power, TDP)范围内最大化处理器性能.
传统商用的睿频技术通过频率和电压调节, 以不成比例的功率和能源消耗为代价, 实现适度的性能增益[7]. 睿频由嵌入式硬件控制器的固件控制, 除了启用/禁用睿频功能之外, 软件几乎无法控制睿频. 然而仅依赖固件控制器打开睿频功能, 无法最大化睿频的效果. 针对上述问题, 不少学者在传统睿频的基础上进行研究与改进. Richins等人[8]根据应用程序特性来激活/停用睿频来加速串行和并行代码的执行. Kondguli等人[1]提出自适应睿频技术, 设计前瞻线程了解代码行为, 将资源投入到具有最佳估计性能收益的核心中. Marques等人[9]将睿频技术与动态并发节流技术(dyna-mic concurrency throttling, DCT)结合来加速顺序代码、平衡线程的并行执行. Zahedi等人[10]提出了一种计算冲刺的架构, 将频率和电压提升到超过TDP水平, 并运行几秒, 同时根据应用程序阶段和系统条件决定是否冲刺. Leva等人[11]将冲刺应用作为基于时间/事件的混合系统进行分析, 来获得稳定性和性能.
龙芯在处理器动态调频方面也有相应研究. 顾丽红等人[12]根据龙芯2F单核处理器支持软件配置多种不同CPU主频的特性, 编写CPUFreq的驱动代码, 实现龙芯软件层的动态调频的方法; 在龙芯3A1000多核处理器中, 因其各个核心频率不能独立调节, 陈华才等人[13]将动态调频和自动调核结合, 实现单独为每个核设置不同的频率. 龙芯现有的动态调频均是在默频范围内进行调节, 当处理器需要运行在超过默频的高频时, 处理器电压需调节到高压, 否则处理器将无法稳定运行在超过默频的高频, 从而无法实现睿频功能. 然而在龙芯动态调压方面的研究较少. 现有的龙芯处理器多数运行在恒定电压, 而龙芯3A4000处理器若利用处理器核来调节自身电压则会有以下问题: (1) 影响CPU负载的正常运行: 在调频调压过程中, 处理器核需实时监测自身的频率和电压的状态, 即处理器核直到一次调频调压结束后才会去运行CPU负载, 而调频调压涉及到硬件操作, 完成调频调压的时间无法确定, 若系统运行进行多次的调频调压操作, 那么处理器核将无法正常运行CPU负载; (2) 缺少对温度的控制: 由于系统将温度和频率割裂管理, 当处理器运行在高压高频时, 芯片的温度会上升, 若此时对温度控制管理不及时, 芯片将会面临被烧坏的风险. 同时, 现有的Intel、AMD睿频技术由于处理器指令集和微架构的差异、代码闭源等因素, 无法将睿频技术直接从Intel或AMD平台移植到龙芯平台. 针对上述问题, 本文根据龙芯3A4000设计的特点和Intel、AMD平台的睿频思想[14, 15], 提出龙芯平台基于系统管理核(system mangement controller, SMC)的睿频方法, 利用SMC实时监测调节处理器核的频率和电压, 同时, 利用SMC监测并控制芯片的温度, 最终实现综合考量频率、电压、温度的龙芯睿频技术.
1 基于SMC的龙芯睿频设计 1.1 总体框架设计睿频技术需要处理器硬件和软件支持. 在硬件支持方面, 龙芯3A4000处理器在硬件上支持多种分级电源状态[16], 利用处理器核分频设置寄存器可设置各个核的主频, 利用电源管理芯片(power management IC, PMIC)可管理处理器核的电压; 在软件支持方面, 睿频技术基于Linux内核的CPUFreq子系统[17]实现, 提供龙芯3A4000的CPUFreq驱动就可以使用CPUFreq提供的调频策略, 如Ondemand、Conservative、Performance等频率调节策略.
基于SMC的龙芯睿频的整体流程如下: 首先, 龙芯3A4000的每个处理器核根据用户接口传递的参数或CPUFreq governor中的调频策略来确定其要调节的目标频率并通过CPUFreq core模块传递给CPUFreq driver模块; 接着, 处理器核获取到CPUFreq driver模块中的目标频率后向SMC下达调频命令; 最后, SMC根据命令去调节频率、电压等相关寄存器的值, 并将执行完成后的结果反馈给处理器核. 同时在SMC中加入温度控制功能, 并实时监控处理器核的频率电压温度状况. 龙芯3A4000基于SMC实现睿频的整体框架图如图1所示.
1.2 SMC的功能设计
由图1可知, 龙芯3A4000基于SMC的睿频方法主要分为处理器核部分(CPUFreq子系统)和SMC两部分. 其中SMC部分需要包含动态调频调压功能、温度控制功能、与处理器核交互功能.
为了更好地在SMC上开发功能、管理SMC以及保证SMC的实时性, 本文基于RT-Thread实时操作系统的线程调度功能模块化地编写SMC的各个功能模块, 基于RT-Thread系统的SMC功能设计如图2所示.
图2中主要有3个线程: 采样线程、决策线程和指令线程. 采样线程主要运行温度模块来获取处理器核的温度; 决策线程主要有3部分: 根据温度调节风扇转速模块、频率调节模块和电压调节模块; 指令线程主要运行指令模块, 接收并处理来自处理器核的命令, 实现处理器核和SMC的交互功能. SMC的指令模块收到处理器核的命令后, 决策线程根据命令对相应模块做出相对应的改变, 实现频率和电压的调节功能. 同时, 采样线程会一直读取芯片的温度, 温度过高时会提高风扇转速并降低频率和电压, 实现SMC对处理器核温度控制的功能. SMC基于RT-Thread实时操作系统循环调度这3个线程, 实现对处理器核电压、频率、温度的实时监测与调节.
2 基于SMC的龙芯睿频实现 2.1 调频调压功能
龙芯3A4000利用处理器核软件分频设置寄存器对处理器核进行调频设置, 该寄存器每4位为一个频控域, 每个频控域控制一个处理器核, 其中频控域的低3位为分频系数, 提供多种分级频率[18]. 当龙芯3A4000处理器通过睿频将最高频率从1 800 MHz变为2 000 MHz时, 处理器频率被分为10个等级, 频率表如表1所示. 根据电压芯片能承受的最大电压来确定处理器能稳定运行的最高频率.
龙芯3A4000通过锁相环(phase locked loop, PLL)来调节处理器的频率, 每个时钟配置有3个参数: DIV_REFC、DIV_LOOPC和DIV_OUT. 根据3个参数经式(1)可得出最终的时钟频率:
$\begin{split} & freq=(OSC\_FREQ/DIV\_REFC\times DIV\_LOOPC) \\ &\quad\quad\quad /DIV\_OUT \end{split} $ | (1) |
其中, OSC_FREQ为外部参考时钟频率, 设为100 MHz.
为了减少对PLL和电压的修改, 根据处理器运行的频率将处理器分为3个状态: 空闲(idle)状态、普通(normal)状态和睿频(boost)状态, 同时依次从低到高对应着PLL的3个等级, 如表1的第3列所示. 通过设定最高分频系数和最低分频系数对调频调压的范围进行限制, 其中空闲状态下调节频率的最高等级为4, 即750 MHz; 普通状态下调节频率的最高等级为8, 即1 500 MHz; 睿频状态下调节频率的最高等级为10, 即2 000 MHz. 当PLL状态改变时, 相对应的时钟参数DIV_REFC、DIV_LOOPC、DIV_OUT都需要重新设置. 同时, 为了保持请求一致性, HyperTransport (HT)、片上网络(network-on-chip, NoC)、共享缓存(share cache)、静态随机存储器(static random-access memory, SRAM)也会进行相应的分频操作.
由于现有一个PMIC控制4个处理器核的电压, 因此要根据4个处理器核中的最高频率来判断PLL的最终状态. 电压会随着PLL状态的改变而改变, 空闲状态时电压为1 V, 普通状态时电压为1.15 V, 睿频状态时电压为1.4 V. 当PLL状态升级时, 先升压再升频; 当PLL状态降级时, 先降频再降压. SMC通过I2C控制PMIC实现对处理器核电压的控制. 电压值以毫伏(mV)为单位, 并经过式(2)转换得到最后的数据, 将最后得到的数据写进uP9512s电压芯片, 最终实现调节处理器核电压的功能.
$ V=\left(volt\times1000-210000\right)/6587 $ | (2) |
SMC调节处理器核的频率和电压的整体流程如图3所示.
由图3可知, SMC先获取处理器核温度, 然后根据温度调节风扇的转速, 接着根据4个核中的最高频率判断PLL等级等信息来得出最终的PLL等级, 最后根据PLL等级调整处理器核频率电压以及系统其它组件的频率. SMC的主线程会一直循环运行这个流程, 实现对处理器核频率、电压、温度的实时监测和统一管理.
2.2 温度控制功能温度控制模块是根据传感器获取的温度改变脉冲宽度调制(pulse width modulation, PWM)的占空比来调节相对应的风扇转速, 以此实现芯片的降温, 达到保护芯片的目的.
龙芯3A4000内部集成两个温度传感器, 可以通过采样寄存器进行观测, 在调频时对处理器核的温度进行判断, 判断是否超过设定的安全温度, 若超过则降频. 读取的寄存器的值经过式(3)的计算得出最后处理器核的温度.
$ Temp=\left[\left(data\&{\rm{0xFFFF}}\right)\times731\right]/0{\rm x}4000-273 $ | (3) |
其中, data为从温度采样寄存器读取的值. 处理器工作时的温度范围应为–40 ℃至125 ℃, 即Temp的取值范围在–40 ℃至125 ℃之间.
SMC根据获取到的温度进行风扇转速的调节. 龙芯3A4000处理器采用自研的7A1000桥片, 将桥片集成的PWM接口和对处理器核的温度监测相结合, 并应用于散热器风扇的转速控制上. PWM调节风扇转速根据不同温度会有不同的占空比从而风扇会有不同的转速, 温度越高, 占空比越高, 风扇转速就越快. 利用PWM的低脉冲宽度寄存器用来配置PWM输出的周期信号的低电平, 脉冲周期宽度寄存器用来配置总周期的长度, 单位为PWM模块的时钟周期. 设置总周期长度为255, 通过改变低电平的长度来改变占空比, 实现对风扇转速的控制. 本文将风扇转速划分为5个等级, 如表2所示.
风扇有两种模式, 一种为人工(manual)模式, 一种为自动(auto)模式, 将风扇设置为自动模式, 在调频调压的过程中, SMC会一直根据从传感器获取的温度按照表2来调节风扇的转速.
2.3 SMC与处理器核的交互功能 2.3.1 核间通信由于处理器核和SMC是相互独立的核, 需建立核间通信才能完成命令的传递和结果的反馈. 选取处理器核和SMC共享的、均能访问到的32位邮箱寄存器作为中间传递寄存器并进行核间通信. 处理器核将命令内容放在邮箱寄存器中, SMC的指令模块轮询读取命令并根据命令进行相对应的操作. SMC处理完成后, 将反馈给处理器核的结果放在邮箱寄存器, 处理器核轮询读取结果. 图4为处理器核和SMC利用邮箱寄存器进行核间通信的大致过程.
为保证处理器核和SMC之间的快速通信, 在核间通信的基础上, 设计了一套“Service Request”的通讯协议. 在寄存器的内部定义了一个smc_message的结构体, smc_message由1位命令是否完成的标志位complete、7位命令类型cmd和24位参数arg组成, 以此来建立各种命令. 处理器核按照“Service Request”协议向SMC下达的命令可分为特征使能、获取频率等级、获取频率信息、获取特征和设置频率等级. 其中, 当命令为调频时, 参数为频率索引.
2.3.2 处理器核的驱动支持
正如第1.1节所述, 龙芯3A4000处理器实现睿频技术需添加相应的CPUFreq驱动支持. 在SMC功能大致实现后, 将龙芯3A4000处理器的相关参数提交给CPUFreq子系统, 往CPUFreq core模块注册相应的驱动. 在龙芯3A4000的CPUFreq driver模块中定义cpufreq_driver类型的loongson3_cpufreq_driver变量, 该变量中需实现的几个具体的功能函数如下:
(1) init(): 在注册龙芯驱动时调用, 具体的工作是初始化cpufreq_policy等相关的数据结构; 提供10级频率表等.
(2) verify(): 校验CPUFreq governor调频策略提供的目标频率的有效性.
(3) target_index(): 在切换频率时调用. 根据要调节的目标频率在频率表中找到对应的频率索引.
(4) get(): 获取当前CPU的频率.
(5) exit(): 在驱动退出时调用.
当处理器核根据调频策略确定要调节的目标频率后, 经过CPUFreq driver中的target_index()函数指针从表1频率表中得出相应的目标频率索引. 处理器核将频率索引作为调频命令的参数通过核间通信发送给SMC. 龙芯基于SMC的睿频流程图如图5所示.
图5分成左右两部分, 分别对应着处理器核和SMC. 处理器核在向SMC下达调频命令后, 剩下的调频步骤全都在SMC内完成, 处理器核只需要轮询读取邮箱寄存器的内容, 根据内容判断是否调频成功. 此种睿频方法可以使处理器核在不影响正常CPU负载运行的情况下进行快速的调频调压. 同时, SMC会一直循环图3的调频调压的整个逻辑流程, 实时监测并调节处理器核的频率、电压和温度状态. 最终在龙芯平台上既实现了根据CPU负载进行动态调频调压又实现了对频率、电压、温度综合考量的睿频方法.
3 实验测试与分析
本节通过实验从性能和功耗两方面对本文提出的基于SMC的睿频方法进行综合评估. 实验平台是龙芯3A4000处理器, 操作系统为Fedora 28, 使用Linux内核5.4.66, 内存为DDR4 2400 8 GB内存. 龙芯3A4000默认的标准频率是1.8 GHz, 此时处理器核的电压为1.25 V, 系统运行期间频率和电压都不会改变. 当处理器核检测到SMC有调频功能时, 在/sys/devices/system/cpu/cpufreq文件夹下会生成boost文件, 手动将boost置1后, 处理器的最高频率变为2 000 MHz, 此时处理器核开启睿频功能, 即基于SMC的龙芯睿频方法生效. 用“lscpu”命令可查看当前处理器的相关信息, 图6为龙芯3A4000处理器开启睿频后的处理器信息图.
由图6可知, 此时, 处理器支持的最高频率为2 000 MHz, 最低频率为187 MHz, 分别与表1的第10级和第1级频率相对应.
实验将现有的没有睿频功能的情况(频率为默频1.8 GHz、电压恒为1.25 V)和开启睿频功能的情况(即本文提出的基于SMC的睿频方法生效后的情况, 最高频率为2 GHz、电压最高为1.4 V)进行对比. 为了更好地分析开启睿频功能后的性能和功耗情况, 又将开启睿频功能的情况细分为采取Ondemand (按需)策略的睿频情况和Performance (性能)策略的睿频情况. 其中Ondemand (按需)策略会根据运行时的CPU负载动态调节频率, Performance (性能)策略会让处理器一直运行在最高频.
实验分为两个部分: 第1部分使用Unixbench基准程序来获得3种情况的综合性能数据; 第2部分获得3种情况在运行Unixbench基准程序时的功耗情况.
3.1 性能测试本节采用性能测试工具Unixbench测试3种情况下的龙芯3A4000处理器的综合性能. Unixbench从系统调用、IO读写、进程、管道、运算等多方面进行性能测试, 能较为全面地综合评价系统各方面性能, 其默认测试集由dhry、whets、execl、fstime、fsbuffer、fsdisk、pipe、context1、spawn、syscall、shell1和shell8这13个基准测试程序组成,具体描述如表3最后一列所示.
Unixbench测试默认会运行单路和4路并行测试. 由于本实验环境中, 一个电压芯片控制4个处理器核的电压, 当处理器开启睿频功能并处于满负载时, 处理器频率会调节到最高频, 电压会被调节到最高压, 此时4个处理器核的频率均可以调节到最高频率. 为了更好地体现睿频后性能提升的效果, 取4路并行测试结果进行分析, 使用“./Run -c 4 index”命令对所包含的测试程序进行4路测试. 龙芯3A4000在3种情况下运行Unixbench性能测试的结果如表3所示, 第2–13行分别对应着Unixbench中的各项性能测试的名称、3种情况各项性能测试分数以及对性能测试项的描述, 最后一行是Unixbench测试得出的3种情况的综合性能分数.
从表3的最后一组(system benchmarks index score)综合性能分数来看, 睿频后处理器无论是运行CPU密集型任务(dhrystone、whetstone、pipe throughput、system call overhead)还是IO密集型任务(文件系统相关任务file copy)还是进程创建、切换相关任务(excel throughput、pipe-based context switching、process creation、shell scripts)都可以看到睿频带来的性能提升, 并且处理器无论是采用按需策略还是性能策略, 综合性能都有一定的提升, 其中按需策略性能提升了约25.6%, 性能策略性能提升了约34.2%. 因为采用性能策略时处理器一直运行在最高频, 按需策略在任务切换空隙时处理器负载降低, 处理器核运行的频率随之降低, 运行测试程序时为满负载状态, 处理器核的频率又会回到最高频, 所以按需策略相较性能策略分数略低.
3.2 功耗测试
在功耗测试中, 在3种情况运行Unixbench测试的同时, 利用功率计66205测量整机功耗, 并计算得出平均功耗进行对比, 功耗测量结果如表4所示.
由表4可知, 在空闲状态下, 处理器睿频后采用按需策略时功耗最低, 原因是空闲状态下处理器一直处于最低频率187 MHz, 与处理器没有睿频功能时一直运行在1 800 MHz时的功耗相比, 功耗降低了33.4%. 处理器采用性能策略时运行频率一直在2 000 MHz, 与其恒运行在1 800 MHz频率功耗相比, 略有提升.
在运行Unixbench测试程序期间, 处理器开启睿频功能采用按需策略与其采用性能策略相比, 因按需策略不会一直运行在最高频, 所以功耗较低; 但由于Unixbench测试大多数情况都是处理器满负载的情况, 所以处理器运行这两个策略之间的功耗相差不大. 处理器采用按需和性能策略比其恒运行在1 800 MHz时平均功耗分别提高了23.3%、25.5%. 除了频率和电压的升高, 还有散热的问题也会导致整体功耗的提高.
综合第3.1节的性能测试和第3.2节的功耗测试结果, 龙芯3A4000基于SMC的睿频方法与未进行睿频的情况相比, 按需策略满负载时性能提升了25.6%、功耗提高了23.3%, 空闲时功耗降低了33.4%; 性能策略满负载时性能提升了34.2%、功耗提高了25.5%, 空闲时功耗相差不大. 由此得出, 龙芯3A4000基于SMC的睿频方法虽增加了功耗, 但性能提升的效果更明显. 在实际情况中, 处理器不会一直运行在满负载的情况下, 使用按需策略动态调节电压和频率, 既可以在高负载的时候提高处理器的频率和电压来提高运算能力, 也可以在低负载的时候降低处理器的频率和电压来降低能耗. 用户可以根据自己的需求选择是否开启睿频、选择合适的调频策略, 以此来满足更好的用户体验.
4 结论与展望龙芯3A4000之前的处理器无法动态调节自身电压, 这不仅阻碍了频率提升到高频, 也阻碍了能耗的节约. 本文提出了基于SMC的睿频方法, 让龙芯3A4000处理器可以运行在超过默认频率的高频, 在提高电压来维持高频稳定运行的同时, 对处理器芯片温度进行监测保护, 提高了系统可靠性. 通过性能测试和功耗测试来验证该方法的可行性, 实验结果表明, 该方法有效且可靠.
未来的研究工作在完善SMC温度散热控制、电压细粒度快速调节的同时, 还要完善龙芯平台下的调频策略等, 使龙芯处理器能提升到更高的主频, 达到能耗和性能之间更好的平衡点.
[1] |
Kondguli S, Huang M. A case for a more effective, power-efficient turbo boosting. ACM Transactions on Architecture and Code Optimization, 2018, 15(1): 5. DOI:10.1145/3170433 |
[2] |
Kalmbach M, Gottschlag M, Schmidt T, et al. TurboCC: A practical frequency-based covert channel with Intel turbo boost. arXiv: 2007.07046, 2020.
|
[3] |
Brookwood N. EPYC(霄龙)处理器高能效CPU设计研究. 中国集成电路, 2020, 29(11): 31-36. DOI:10.3969/j.issn.1681-5289.2020.11.007 |
[4] |
郭兵, 张鹏博, 沈艳, 等. 基于BP神经网络的处理器节能技术研究. 工程科学与技术, 2018, 50(1): 107-112. DOI:10.15961/j.jsuese.201700175 |
[5] |
Zhang W, Zhang H, Lash J. Extending performance-energy trade-offs via dynamic core scaling. IEEE Transactions on Computers, 2021, 70(11): 1875-1886. DOI:10.1109/TC.2020.3029306 |
[6] |
Scordino C, Abeni L, Lelli J. Real-time and energy efficiency in Linux: Theory and practice. ACM SIGAPP Applied Computing Review, 2019, 18(4): 18-30. DOI:10.1145/3307624.3307627 |
[7] |
Marques SMVN, Medeiros TS, Rossi FD, et al. The impact of turbo frequency on the energy, performance, and aging of parallel applications. 2019 IFIP/IEEE 27th International Conference on Very Large Scale Integration. Cuzco: IEEE, 2019.
|
[8] |
Richins D, Ahmed T, Clapp R, et al. Amdahl’s law in big data analytics: Alive and kicking in TPCx-BB (BigBench). IEEE International Symposium on High Performance Computer Architecture. Vienna: IEEE, 2018.
|
[9] |
Marques SM, Medeiros TS, Serpa M, et al. Optimizing parallel applications via dynamic concurrency throttling and turbo boosting. 2021 29th Euromicro International Conference on Parallel, Distributed and Network-based Processing (PDP). Valladolid: IEEE, 2021, 153-160. DOI:10.1109/PDP52278.2021.00032 |
[10] |
Zahedi SM, Fan SC, Faw M, et al. Computational sprinting: Architecture, dynamics, and strategies. ACM Transactions on Computer Systems, 2017, 34(4): 12. DOI:10.1145/3014428 |
[11] |
Leva A, Terraneo F, Cimino C, et al. An event-based multi-purpose approach to computational sprinting. IFAC-PapersOnLine, 2019, 52: 38-43. DOI:10.1016/j.ifacol.2019.12.729 |
[12] |
顾丽红, 林志强, 吴少刚. 基于龙芯的软件层动态变频研究与实现. 计算机工程, 2011, 37(9): 41-43. DOI:10.3969/j.issn.1000-3428.2011.09.014 |
[13] |
陈华才, 张福新, 王剑. CPUAutoplug: 动态变频与自动调核相结合的电源管理方法. 小型微型计算机系统, 2015, 35(11): 2586-2592. |
[14] |
Zhou L, Zhang FW, Xiao JD, et al. A coprocessor-based introspection framework via Intel management engine. IEEE Transactions on Dependable and Secure Computing, 2021, 18(4): 1920-1932. DOI:10.1109/TDSC.2021.3071092 |
[15] |
Zhang FW, Zhang HW. SoK: A study of using hardware-assisted isolated execution environments for security. Proceedings of the Hardware and Architectural Support for Security and Privacy 2016. New York: Association for Computing Machinery, 2016.
|
[16] |
黄伟. 基于龙芯平台的桌面操作系统电源管理技术的研究与实现[硕士学位论文]. 南京: 南京邮电大学, 2019.
|
[17] |
赵婉芳. Linux系统中CPUFreq电源管理模块的探究与应用. 数字技术与应用, 2018, 36(10): 67-68. DOI:10.19695/j.cnki.cn12-1369.2018.10.33 |
[18] |
陈华才. 用“芯”探核: 基于龙芯的Linux内核探索解析. 北京: 人民邮电出版社, 2020.
|